{"record":{"id":"0ed72ad47e6e8350","repo":"plandex-ai/plandex","slug":"error-setting-plan-status-to-building-v","errorCode":null,"errorMessage":"error setting plan status to building: %v","messagePattern":"error setting plan status to building: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"app/server/model/plan/build_exec.go","lineNumber":83,"sourceCode":"\t\treturn 0, err\n\t}\n\n\tpendingBuildsByPath, err := state.loadPendingBuilds(sessionId)\n\tif err != nil {\n\t\treturn onErr(err)\n\t}\n\n\tif len(pendingBuildsByPath) == 0 {\n\t\tlog.Println(\"No pending builds\")\n\t\tstreamDone()\n\t\treturn 0, nil\n\t}\n\n\terr = db.SetPlanStatus(plan.Id, branch, shared.PlanStatusBuilding, \"\")\n\n\tif err != nil {\n\t\tlog.Printf(\"Error setting plan status to building: %v\\n\", err)\n\t\treturn onErr(fmt.Errorf(\"error setting plan status to building: %v\", err))\n\t}\n\n\tlog.Printf(\"Starting %d builds\\n\", len(pendingBuildsByPath))\n\n\tfor _, pendingBuilds := range pendingBuildsByPath {\n\t\tgo state.queueBuilds(pendingBuilds)\n\t}\n\n\treturn len(pendingBuildsByPath), nil\n}\n\nfunc (state *activeBuildStreamState) queueBuild(activeBuild *types.ActiveBuild) {\n\tplanId := state.plan.Id\n\tbranch := state.branch\n\n\tfilePath := activeBuild.Path\n\n\t// log.Printf(\"Queue:\")","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/plan/build_exec.go#L65-L101","documentation":"Build sets the plan's status to PlanStatusBuilding before queueing pending builds. If db.SetPlanStatus fails, it logs the cause, invokes the onErr handler, and returns \"error setting plan status to building: %v\". The build is aborted because a stale/unknown status would break downstream state transitions.","triggerScenarios":"db.SetPlanStatus(plan.Id, branch, PlanStatusBuilding, \"\") returns an error: DB connection failure, transaction timeout, missing plan/branch row (plan deleted between checks), or schema mismatch.","commonSituations":"DB unreachable during a deploy, plan row removed by a concurrent delete, migration lag, or file/sqlite DB lock contention under heavy concurrent builds.","solutions":["Fix the underlying DB issue surfaced in the wrapped %v message (connectivity, auth, schema).","Verify the plan row for that ID/branch still exists before building.","Retry transient DB failures with backoff before invoking onErr.","Run pending migrations to ensure the plan status columns match the code."],"exampleFix":"// before: single attempt\nerr = db.SetPlanStatus(plan.Id, branch, shared.PlanStatusBuilding, \"\")\nif err != nil { return onErr(fmt.Errorf(...)) }\n// after: retry transient errors\nerr = retryTransient(3, func() error { return db.SetPlanStatus(plan.Id, branch, shared.PlanStatusBuilding, \"\") })\nif err != nil { return onErr(fmt.Errorf(\"error setting plan status to building: %v\", err)) }","handlingStrategy":"retry","validationCode":"plan, err := db.GetPlan(planId)\nif err != nil || plan == nil {\n    return fmt.Errorf(\"plan %s missing before build; skip status update\", planId)\n}","typeGuard":null,"tryCatchPattern":"err := Build(ctx, plan, branch)\nif err != nil && strings.Contains(err.Error(), \"error setting plan status to building\") {\n    time.Sleep(time.Second)\n    err = Build(ctx, plan, branch) // retry transient DB failure\n}","preventionTips":["Retry transient DB errors with exponential backoff before failing the build","Ensure migrations run before builds start after a deploy","Guard against concurrent plan deletion with existence checks","Watch DB error logs during build-heavy periods"],"tags":["database","state-management","build"],"backgroundTag":"database-write-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"}