Summary
ClassDetailPage fetches the study plan on every load regardless of whether an exam date is set. When no plan has been created yet, the backend throws a generic RuntimeException (→ HTTP 500) instead of a clean 404.
Steps to Reproduce
- Navigate to any
ClassDetailPage for a class without an exam date set
- Observe the network request to
GET /api/classes/{classId}/study-plan
- Observe the resulting 500 error in the backend logs
Expected Behaviour
- The study plan API call is only made if the class has an exam date set (study plans are only relevant with an exam date).
- When a class has an exam date but no study plan has been created yet,
GET /api/classes/{classId}/study-plan returns HTTP 404 — not 500 — because the absence of a plan is a valid, expected state.
Actual Behaviour
useStudyPlan(id) is called unconditionally at ClassDetailPage.tsx:61, triggering an unnecessary API request even when no exam date exists.
StudyPlanService.getStudyPlan() (StudyPlanService.java:108) throws new RuntimeException("No study plan found for this class") when no plan exists, which Spring maps to HTTP 500.
Environment
| Field |
Value |
| Environment |
all |
| Module |
minerva-api, minerva-hub |
| Browser |
n/a |
| Triggered by |
Navigating to ClassDetailPage for any class |
Affected Module(s)
Severity
Suspected Cause
- Frontend (
ClassDetailPage.tsx:61): useStudyPlan(id) has no guard for classData.examDate. The condition canCreateStudyPlan already checks classData.examDate at line 252, but the fetch itself does not.
- Backend (
StudyPlanService.java:108): Uses orElseThrow(() -> new RuntimeException(...)) instead of a typed NotFoundException / ResponseStatusException(HttpStatus.NOT_FOUND).
Proposed Fix
minerva-hub — ClassDetailPage.tsx: Pass the classId to the hook only when the exam date is set:
// only fetch when exam date is present
const { data: studyPlan } = useStudyPlan(classData?.examDate ? id : undefined);
minerva-api — StudyPlanService.java:108: Replace the generic RuntimeException with a proper not-found exception so the endpoint returns HTTP 404 instead of 500.
Logs / Stack Trace
RuntimeException: No study plan found for this class
at StudyPlanService.getStudyPlan(StudyPlanService.java:108)
Summary
ClassDetailPagefetches the study plan on every load regardless of whether an exam date is set. When no plan has been created yet, the backend throws a genericRuntimeException(→ HTTP 500) instead of a clean 404.Steps to Reproduce
ClassDetailPagefor a class without an exam date setGET /api/classes/{classId}/study-planExpected Behaviour
GET /api/classes/{classId}/study-planreturns HTTP 404 — not 500 — because the absence of a plan is a valid, expected state.Actual Behaviour
useStudyPlan(id)is called unconditionally atClassDetailPage.tsx:61, triggering an unnecessary API request even when no exam date exists.StudyPlanService.getStudyPlan()(StudyPlanService.java:108) throwsnew RuntimeException("No study plan found for this class")when no plan exists, which Spring maps to HTTP 500.Environment
Affected Module(s)
minerva-apiminerva-hubSeverity
isErrorgracefully and doesn't retry on 404/500, but the 500 pollutes logs and the unnecessary call wastes a round-trip)Suspected Cause
ClassDetailPage.tsx:61):useStudyPlan(id)has no guard forclassData.examDate. The conditioncanCreateStudyPlanalready checksclassData.examDateat line 252, but the fetch itself does not.StudyPlanService.java:108): UsesorElseThrow(() -> new RuntimeException(...))instead of a typedNotFoundException/ResponseStatusException(HttpStatus.NOT_FOUND).Proposed Fix
minerva-hub—ClassDetailPage.tsx: Pass theclassIdto the hook only when the exam date is set:minerva-api—StudyPlanService.java:108: Replace the genericRuntimeExceptionwith a proper not-found exception so the endpoint returns HTTP 404 instead of 500.Logs / Stack Trace