{"record":{"id":"49fe62fd9d50d7d1","repo":"plandex-ai/plandex","slug":"panic-in-getfullcurrentplanstateparams-v-n-s","errorCode":null,"errorMessage":"panic in GetFullCurrentPlanStateParams: %v\\n%s","messagePattern":"panic in GetFullCurrentPlanStateParams: (.+?)\\\\n(.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":75,"sourceCode":"\tOrgId                    string\n\tPlanId                   string\n\tPlanFileResults          []*PlanFileResult\n\tConvoMessageDescriptions []*ConvoMessageDescription\n\tContexts                 []*Context\n}\n\nfunc GetFullCurrentPlanStateParams(orgId, planId string) (CurrentPlanStateParams, error) {\n\terrCh := make(chan error, 3)\n\n\tvar results []*PlanFileResult\n\tvar convoMessageDescriptions []*ConvoMessageDescription\n\tvar contexts []*Context\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tlog.Printf(\"panic in GetFullCurrentPlanStateParams: %v\\n%s\", r, debug.Stack())\n\t\t\t\terrCh <- fmt.Errorf(\"panic in GetFullCurrentPlanStateParams: %v\\n%s\", r, debug.Stack())\n\t\t\t\truntime.Goexit() // don't allow outer function to continue and double-send to channel\n\t\t\t}\n\t\t}()\n\n\t\tres, err := GetPlanFileResults(orgId, planId)\n\t\tif err != nil {\n\t\t\terrCh <- fmt.Errorf(\"error getting plan file results: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tresults = res\n\t\terrCh <- nil\n\t}()\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tlog.Printf(\"panic in GetFullCurrentPlanStateParams: %v\\n%s\", r, debug.Stack())\n\t\t\t\terrCh <- fmt.Errorf(\"panic in GetFullCurrentPlanStateParams: %v\\n%s\", r, debug.Stack())","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L57-L93","documentation":"GetFullCurrentPlanStateParams fans out three goroutines, each guarded by a defer/recover. If the goroutine that calls GetPlanFileResults panics, the panic is captured, logged with a stack trace, converted into this error, and sent on errCh so the caller receives it instead of the process crashing.","triggerScenarios":"A panic inside the first worker goroutine while fetching plan file results — typically nil map/slice access or a nil pointer dereference on corrupted result data inside GetPlanFileResults.","commonSituations":"Corrupt or hand-edited JSON result files triggering unexpected code paths; a nil receiver bug introduced in db helpers after an upgrade; out-of-range index on malformed stored results.","solutions":["Use the logged stack trace (debug.Stack output) to find the panicking line","Inspect the result JSON files for the plan and fix/remove corrupt entries","Update the db package to a version where the panicking bug is fixed","Call GetFullCurrentPlanStateParams in a wrapper that retries once after validating storage","Report/reproduce with the same orgId/planId and dump the results directory contents"],"exampleFix":"// before\nparams, err := db.GetFullCurrentPlanStateParams(orgId, planId)\n// after\nparams, err := db.GetFullCurrentPlanStateParams(orgId, planId)\nif err != nil && strings.Contains(err.Error(), \"panic in GetFullCurrentPlanStateParams\") {\n\tlog.Printf(\"panic while loading plan state for %s/%s: %v\", orgId, planId, err)\n}","handlingStrategy":"try-catch","validationCode":"// validate storage readability before calling\nif _, err := db.GetPlanFileResults(orgId, planId); err != nil {\n\treturn fmt.Errorf(\"plan results storage unhealthy: %w\", err)\n}","typeGuard":"func isPanicError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"panic in \")\n}","tryCatchPattern":"params, err := db.GetFullCurrentPlanStateParams(orgId, planId)\nif isPanicError(err) {\n\tlog.Printf(\"internal panic loading plan state (see server stack trace): %v\", err)\n\treturn nil, err\n}","preventionTips":["Keep the server log alongside this error — the stack trace is included in the message","Avoid hand-editing result JSON files under the plans data dir","Run integration tests against representative stored data after upgrades","Pin db package versions and read changelogs for concurrency fixes","Call with distinct orgId/planId to isolate whether corruption is plan-specific"],"tags":["go","panic","goroutine","concurrency"],"backgroundTag":"goroutine-panic-recovered","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}