{"record":{"id":"7b7e51edbc30f114","repo":"plandex-ai/plandex","slug":"error-getting-current-plan-state-v-7b7e51","errorCode":null,"errorMessage":"error getting current plan state: %v","messagePattern":"error getting current plan state: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/model/plan/build_load.go","lineNumber":239,"sourceCode":"\n\terr = db.ExecRepoOperation(db.ExecRepoOperationParams{\n\t\tOrgId:       currentOrgId,\n\t\tUserId:      state.activeBuildStreamState.currentUserId,\n\t\tPlanId:      planId,\n\t\tBranch:      branch,\n\t\tPlanBuildId: build.Id,\n\t\tScope:       db.LockScopeRead,\n\t\tCtx:         activePlan.Ctx,\n\t\tCancelFn:    activePlan.CancelFn,\n\t\tReason:      \"load build file\",\n\t}, func(repo *db.GitRepo) error {\n\t\terrCh := make(chan error, 2)\n\n\t\tgo func() {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tlog.Printf(\"panic in getCurrentPlanState: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\terrCh <- fmt.Errorf(\"error getting current plan state: %v\", r)\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\t\t\tlog.Println(\"loadBuildFile - Getting current plan state\")\n\t\t\tres, err := db.GetCurrentPlanState(db.CurrentPlanStateParams{\n\t\t\t\tOrgId:  currentOrgId,\n\t\t\t\tPlanId: planId,\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"Error getting current plan state: %v\\n\", err)\n\t\t\t\tUpdateActivePlan(activePlan.Id, activePlan.Branch, func(ap *types.ActivePlan) {\n\t\t\t\t\tap.IsBuildingByPath[filePath] = false\n\t\t\t\t})\n\t\t\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error getting current plan state: %v\", err))\n\n\t\t\t\tactivePlan.StreamDoneCh <- &shared.ApiError{\n\t\t\t\t\tType:   shared.ApiErrorTypeOther,\n\t\t\t\t\tStatus: http.StatusInternalServerError,","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/plan/build_load.go#L221-L257","documentation":"Inside loadBuildFile, the goroutine that calls db.GetCurrentPlanState is wrapped in a recover() defer. If that goroutine panics, the panic value r is logged with a stack trace, converted to an error via fmt.Errorf(\"error getting current plan state: %v\", r), and sent to errCh; then runtime.Goexit() stops the goroutine so it cannot double-send. This error therefore means the plan-state fetch crashed (nil pointer, index out of range, etc.) rather than returning a normal db error.","triggerScenarios":"A panic occurs inside the goroutine running db.GetCurrentPlanState(db.CurrentPlanStateParams{OrgId, PlanId}) during loadBuildFile — e.g. nil deref or out-of-range access in the db layer while loading plan state for the org/plan.","commonSituations":"Corrupt or unexpected plan state data in the store triggering a nil map/slice access in db.GetCurrentPlanState; concurrent mutation of ActivePlan state while the load runs; a bug in a recently changed db helper invoked by GetCurrentPlanState.","solutions":["Check the goroutine's panic stack trace printed just before this error for the exact nil-deref/bounds line in db.GetCurrentPlanState","Verify the plan state record for the given OrgId/PlanId is not corrupt or null-shaped (missing expected nested fields)","Harden db.GetCurrentPlanState against missing/nil nested structures before use","Re-run the build load after fixing; the plan is unlocked and IsBuildingByPath reset in the outer error path"],"exampleFix":"// before\nres, err := db.GetCurrentPlanState(db.CurrentPlanStateParams{OrgId: currentOrgId, PlanId: planId}) // panics on nil state\n// after\nif currentOrgId == \"\" || planId == \"\" {\n\terrCh <- fmt.Errorf(\"error getting current plan state: missing orgId or planId\")\n\treturn\n}\nres, err := db.GetCurrentPlanState(db.CurrentPlanStateParams{OrgId: currentOrgId, PlanId: planId})","handlingStrategy":"try-catch","validationCode":"if currentOrgId == \"\" || planId == \"\" {\n\treturn fmt.Errorf(\"orgId and planId are required\")\n}","typeGuard":"func hasPlanStateParams(orgId, planId string) bool { return orgId != \"\" && planId != \"\" }","tryCatchPattern":"res, err := safeGetCurrentPlanState(currentOrgId, planId)\nif err != nil {\n\tlog.Printf(\"plan state unavailable: %v\", err)\n\treturn err\n}","preventionTips":["Keep db.GetCurrentPlanState nil-safe for missing plan state","Check panic stack traces in logs for the root db-layer bug","Test plan-state loading for missing/malformed plans"],"tags":["go","panic","concurrency","database"],"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"}