{"record":{"id":"f5db249b1c7dff8d","repo":"plandex-ai/plandex","slug":"error-loading-plan-v","errorCode":null,"errorMessage":"error loading plan: %v","messagePattern":"error loading plan: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/model/plan/tell_load.go","lineNumber":314,"sourceCode":"\t\t\t\t\terrCh <- fmt.Errorf(\"error getting plan subtasks: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\truntime.Goexit() // don't allow outer function to continue and double-send to channel\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tres, err := db.GetPlanSubtasks(auth.OrgId, planId)\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"Error getting plan subtasks: %v\\n\", err)\n\t\t\t\terrCh <- fmt.Errorf(\"error getting plan subtasks: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsubtasks = res\n\t\t\terrCh <- nil\n\t\t}()\n\n\t\tfor i := 0; i < 4; i++ {\n\t\t\terr = <-errCh\n\t\t\tif err != nil {\n\t\t\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error loading plan: %v\", err))\n\n\t\t\t\tactive.StreamDoneCh <- &shared.ApiError{\n\t\t\t\t\tType:   shared.ApiErrorTypeOther,\n\t\t\t\t\tStatus: http.StatusInternalServerError,\n\t\t\t\t\tMsg:    fmt.Sprintf(\"Error loading plan: %v\", err),\n\t\t\t\t}\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tres, err := db.GetCurrentPlanState(db.CurrentPlanStateParams{\n\t\t\tOrgId:    currentOrgId,\n\t\t\tPlanId:   planId,\n\t\t\tContexts: modelContext,\n\t\t})\n\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error getting current plan state: %v\", err)","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/plan/tell_load.go#L296-L332","documentation":"Aggregation error in tell_load.go: after launching four parallel loader goroutines (convo/store message, plan summaries, plan subtasks, settings), the parent collects four results from errCh; the first non-nil is reported as 'error loading plan: %v', sent to Sentry-like notify, and pushed to the client as a 500 ApiError on StreamDoneCh. It is the umbrella for any of the child load errors (740-742 etc.).","triggerScenarios":"Any of the four loader goroutines sends a non-nil error: failed user-message store, GetPlanSummaries error, GetPlanSubtasks error (including recovered panics), or a settings load failure.","commonSituations":"DB outage during plan load; one of the child queries failing due to schema drift or a race; plan deleted mid-load so a child query fails.","solutions":["Read the wrapped child error after 'error loading plan:' to find the root cause","Check the server log lines just before it (the child goroutines log their own errors)","Verify database health and migrations","Retry the plan load once the underlying issue is fixed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if planId == \"\" {\n    active.StreamDoneCh <- &shared.ApiError{Type: shared.ApiErrorTypeOther, Status: http.StatusBadRequest, Msg: \"missing planId\"}\n    return fmt.Errorf(\"missing planId\")\n}","typeGuard":null,"tryCatchPattern":"for i := 0; i < 4; i++ {\n    err = <-errCh\n    if err != nil {\n        go notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error loading plan: %w\", err))\n        active.StreamDoneCh <- &shared.ApiError{Type: shared.ApiErrorTypeOther, Status: http.StatusInternalServerError, Msg: fmt.Sprintf(\"Error loading plan: %v\", err)}\n        return err\n    }\n}","preventionTips":["Always send exactly one nil-or-error per loader goroutine on errCh","Log child errors before wrapping so the root cause is traceable","Add DB health monitoring to catch outages early","Consider context cancellation to avoid orphaned goroutines after first error"],"tags":["aggregation","database","concurrency","http-500"],"backgroundTag":"database-query-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}