{"record":{"id":"0e6451b6acb399d9","repo":"plandex-ai/plandex","slug":"error-storing-plan-config","errorCode":null,"errorMessage":"Error storing plan config","messagePattern":"Error storing plan config","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plan_config.go","lineNumber":85,"sourceCode":"\tlog.Println(\"planId: \", planId)\n\n\tplan := authorizePlan(w, planId, auth)\n\tif plan == nil {\n\t\treturn\n\t}\n\n\tvar req shared.UpdatePlanConfigRequest\n\terr := json.NewDecoder(r.Body).Decode(&req)\n\tif err != nil {\n\t\tlog.Println(\"Error decoding request body: \", err)\n\t\thttp.Error(w, \"Error decoding request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\terr = db.StorePlanConfig(planId, req.Config)\n\tif err != nil {\n\t\tlog.Println(\"Error storing plan config: \", err)\n\t\thttp.Error(w, \"Error storing plan config\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlog.Println(\"UpdatePlanConfigHandler processed successfully\")\n}\n\nfunc GetDefaultPlanConfigHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for GetDefaultPlanConfigHandler\")\n\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tconfig, err := db.GetDefaultPlanConfig(auth.User.Id)\n\tif err != nil {\n\t\tlog.Println(\"Error getting default plan config: \", err)\n\t\thttp.Error(w, \"Error getting default plan config\", http.StatusInternalServerError)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plan_config.go#L67-L103","documentation":"db.StorePlanConfig(planId, req.Config) failed after the body decoded successfully, so the handler returns HTTP 500. This is a server-side persistence failure writing the new plan config, not a client error.","triggerScenarios":"Update-plan-config call when the plan_configs table is missing/locked, the DB transaction fails (deadlock, serialization failure, disk full), or the config value exceeds column limits or violates constraints.","commonSituations":"Database read-only replica receiving writes, migrations not applied, disk full on the DB host, concurrent updates deadlocking, config payload too large for the storage column.","solutions":["Check server logs for \"Error storing plan config: <err>\" for the root cause","Verify the DB is writable and migrations are current","Retry the request if the failure was a transient deadlock/serialization error","Reduce config payload size or widen the storage column if limits are hit"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// client: retry only on 500; 400s mean bad body\nlet lastErr;\nfor (let i = 0; i < 3; i++) {\n  const res = await tryStore(planId, config);\n  if (res.ok) return;\n  if (res.status !== 500) break; // do not retry client errors\n  lastErr = res;\n  await sleep(2 ** i * 250);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await updatePlanConfig(planId, config);\n} catch (e) {\n  if (e.status === 500) { await backoffRetry(e, { attempts: 3 }); }\n  else throw e;\n}","preventionTips":["Ensure the DB is writable (no read-only replicas) and has disk headroom","Apply schema migrations before rollout","Handle deadlocks by retrying the write transaction","Bound config payload size if storage columns are constrained"],"tags":["database","http-500","plan-config"],"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-12T22:17:10.623Z"}