{"record":{"id":"8124fca906b934ca","repo":"plandex-ai/plandex","slug":"error-storing-plan-build-result-v","errorCode":null,"errorMessage":"Error storing plan build result: %v","messagePattern":"Error storing plan build result: (.+?)","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/model/plan/build_finish.go","lineNumber":222,"sourceCode":"\t\tReason:      \"store plan result\",\n\t}, func(repo *db.GitRepo) error {\n\t\tlog.Println(\"Storing plan result\", planRes.Path)\n\n\t\terr := db.StorePlanResult(planRes)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error storing plan result: %v\\n\", err)\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\tlog.Printf(\"Error storing plan build result: %v\\n\", err)\n\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error storing plan build result: %v\", err))\n\n\t\tactivePlan.StreamDoneCh <- &shared.ApiError{\n\t\t\tType:   shared.ApiErrorTypeOther,\n\t\t\tStatus: http.StatusInternalServerError,\n\t\t\tMsg:    \"Error storing plan build result: \" + err.Error(),\n\t\t}\n\t\treturn\n\t}\n\n\tfileState.builderRun.FinishedAt = time.Now()\n\thooks.ExecHook(hooks.DidFinishBuilderRun, hooks.HookParams{\n\t\tAuth:                      fileState.auth,\n\t\tPlan:                      fileState.plan,\n\t\tDidFinishBuilderRunParams: &fileState.builderRun,\n\t})\n\n\tlog.Printf(\"Finished building file %s - setting activeBuild.Success to true\\n\", filePath)\n\t// log.Println(spew.Sdump(activeBuild))\n\n\tfileState.onBuildProcessed(activeBuild)\n}","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/plan/build_finish.go#L204-L240","documentation":"After storing the per-file plan result inside a repo write lock (db.StorePlanResult) or acquiring the lock itself via db.ExecRepoOperation, any error is wrapped/logged as \"Error storing plan build result: %v\" and pushed to StreamDoneCh as a 500 ApiError. It indicates the persistence step of the file build failed — either the repo lock couldn't be acquired (canceled, timed out, deadlocked) or the database write for the PlanFileResult failed.","triggerScenarios":"db.ExecRepoOperation fails to get the write lock (another build holds it, plan context canceled, lock timeout) or db.StorePlanResult returns a database error (connection refused, constraint violation, disk full) for planRes.Path.","commonSituations":"Postgres down or restarting during a build; concurrent builds on the same plan/branch contending for the repo write lock; plan canceled by the user mid-build so the context is canceled; disk exhaustion on the database volume.","solutions":["Read the full wrapped error in the server log to distinguish a lock-acquisition failure from a StorePlanResult DB error","Verify the database is reachable and healthy (connection pool, disk space, migrations)","Retry the plan build if the failure was transient (DB restart, lock contention)","Check for leaked repo locks from crashed builds and ensure ExecRepoOperation releases locks (look for stale lock rows/locks for the plan branch)","Avoid canceling plans mid-build when possible; cancelations can leave operations racing for locks"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before starting builds, verify DB reachability\nif err := db.Ping(); err != nil {\n\treturn fmt.Errorf(\"database unreachable before plan build: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"err := db.ExecRepoOperation(params, func(repo *db.GitRepo) error {\n\treturn db.StorePlanResult(planRes)\n})\nif err != nil {\n\tswitch {\n\tcase errors.Is(err, context.Canceled):\n\t\t// user canceled; don't retry\n\tcase isLockTimeout(err):\n\t\t// retry with backoff\n\tdefault:\n\t\t// DB error: check database health, then retry or alert\n\t}\n}","preventionTips":["Monitor Postgres health and disk space during builds","Keep repo write-lock scope short so concurrent builds don't time out","Implement bounded retries with backoff for transient lock/DB errors","Ensure plan cancellation reliably releases held repo locks"],"tags":["plandex","server","database","locking","persistence"],"backgroundTag":"repo-lock-store-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"}