{"record":{"id":"dbcf57099982e346","repo":"plandex-ai/plandex","slug":"panic-in-getcurrentplanstate-v-n-s","errorCode":null,"errorMessage":"panic in GetCurrentPlanState: %v\\n%s","messagePattern":"panic in GetCurrentPlanState: (.+?)\\\\n(.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":155,"sourceCode":"\t\tContexts:                 contexts,\n\t}, nil\n}\n\nfunc GetCurrentPlanState(params CurrentPlanStateParams) (*shared.CurrentPlanState, error) {\n\torgId := params.OrgId\n\tplanId := params.PlanId\n\n\tvar dbPlanFileResults []*PlanFileResult\n\tvar convoMessageDescriptions []*shared.ConvoMessageDescription\n\tcontextsByPath := map[string]*Context{}\n\tplanApplies := []*shared.PlanApply{}\n\terrCh := make(chan error, 4)\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tlog.Printf(\"panic in GetCurrentPlanState: %v\\n%s\", r, debug.Stack())\n\t\t\t\terrCh <- fmt.Errorf(\"panic in GetCurrentPlanState: %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\t\tif params.PlanFileResults == nil {\n\t\t\tres, err := GetPlanFileResults(orgId, planId)\n\t\t\tdbPlanFileResults = res\n\n\t\t\tif err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"error getting plan file results: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t} else {\n\t\t\tdbPlanFileResults = params.PlanFileResults\n\t\t}\n\n\t\terrCh <- nil\n\t}()\n","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L137-L173","documentation":"GetCurrentPlanState runs four goroutines with per-goroutine recover. If the goroutine that fetches plan file results (only when params.PlanFileResults is nil) panics, the panic is logged with a stack trace, converted to this error, and returned to the caller.","triggerScenarios":"Calling GetCurrentPlanState with params.PlanFileResults == nil so it loads from disk, and GetPlanFileResults panics — e.g. nil map write or nil deref on malformed result data.","commonSituations":"Corrupt result files on disk; a nil-pointer bug in the db helpers after a version change; zero-value CurrentPlanStateParams passed by mistake when caller intended to supply cached results.","solutions":["If you already have results in memory, pass them via params.PlanFileResults to skip the disk load","Use the logged stack trace to pinpoint the panicking line and fix the data or code","Repair or remove corrupt result JSON files","Upgrade the db package to a patched version","Pre-populate CurrentPlanStateParams from GetFullCurrentPlanStateParams instead of passing a zero value"],"exampleFix":"// before\nstate, err := db.GetCurrentPlanState(db.CurrentPlanStateParams{})\n// after\nparams, err := db.GetFullCurrentPlanStateParams(orgId, planId)\nif err != nil {\n\treturn nil, err\n}\nstate, err := db.GetCurrentPlanState(params)","handlingStrategy":"validation","validationCode":"func buildParams(orgId, planId string) (db.CurrentPlanStateParams, error) {\n\tif orgId == \"\" || planId == \"\" {\n\t\treturn db.CurrentPlanStateParams{}, fmt.Errorf(\"orgId and planId required\")\n\t}\n\treturn db.GetFullCurrentPlanStateParams(orgId, planId)\n}\n// then pass the fully-populated params to GetCurrentPlanState","typeGuard":"func paramsComplete(p db.CurrentPlanStateParams) bool {\n\treturn p.OrgId != \"\" && p.PlanId != \"\" && p.PlanFileResults != nil\n}","tryCatchPattern":"state, err := db.GetCurrentPlanState(params)\nif err != nil && strings.Contains(err.Error(), \"panic in GetCurrentPlanState\") {\n\tlog.Printf(\"results goroutine panicked; stack in server log: %v\", err)\n\treturn nil, err\n}","preventionTips":["Never pass a zero-value CurrentPlanStateParams; always populate cached sub-results when available","Supply PlanFileResults explicitly to avoid a redundant disk load","Keep the stack trace from the server log as the primary debugging artifact","Re-verify stored result JSON integrity after crashes or upgrades","Pin and test db package versions in CI with realistic data"],"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"}