{"record":{"id":"a410e4b727b31964","repo":"plandex-ai/plandex","slug":"error-storing-plan-config-v","errorCode":null,"errorMessage":"error storing plan config: %v","messagePattern":"error storing plan config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/plan_config_helpers.go","lineNumber":34,"sourceCode":"\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting plan config: %v\", err)\n\t}\n\n\treturn &config, nil\n}\n\nfunc StorePlanConfig(planId string, config *shared.PlanConfig) error {\n\tquery := `\n\t\tUPDATE plans \n\t\tSET plan_config = $1\n\t\tWHERE id = $2\n\t`\n\n\t_, err := Conn.Exec(query, config, planId)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error storing plan config: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc GetDefaultPlanConfig(userId string) (*shared.PlanConfig, error) {\n\tquery := \"SELECT default_plan_config FROM users WHERE id = $1\"\n\n\tvar config shared.PlanConfig\n\terr := Conn.Get(&config, query, userId)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting default plan config: %v\", err)\n\t}\n\n\treturn &config, nil\n}\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/plan_config_helpers.go#L16-L52","documentation":"StorePlanConfig wraps a failure of `UPDATE plans SET plan_config = $1 WHERE id = $2` with this message. Note the UPDATE silently affects zero rows when planId doesn't exist — this wrap only fires on actual Exec errors: connection failure, driver serialization error for the config, or schema problems.","triggerScenarios":"UpdatePlanConfigHandler calls StorePlanConfig and Conn.Exec fails: DB unreachable, plans table/column missing (migration drift), or the *shared.PlanConfig value cannot be encoded by the driver into plan_config.","commonSituations":"Postgres restart or connection-pool exhaustion during a config save; running against a database without the plan_config column; a PlanConfig containing unsupported field types the lib/pq encoder rejects; concurrent migration changing the schema.","solutions":["Inspect the wrapped cause for connection vs encoding errors; for connection errors check Postgres health and retry","Confirm migrations have created plans.plan_config with the expected type (JSONB/text)","Validate the incoming PlanConfig payload (JSON-serializable, size limits) before storing","After a successful Exec, also check RowsAffected if you need to detect a nonexistent planId, since zero rows is not an error here"],"exampleFix":"// before\nerr := StorePlanConfig(planId, config)\n// after: detect zero-row updates too\nres, err := Conn.Exec(\"UPDATE plans SET plan_config = $1 WHERE id = $2\", config, planId)\nif err != nil { return err }\nn, _ := res.RowsAffected()\nif n == 0 { return fmt.Errorf(\"plan %s not found\", planId) }","handlingStrategy":"validation","validationCode":"// validate payload and target row before the UPDATE\nb, err := json.Marshal(config)\nif err != nil {\n    return fmt.Errorf(\"invalid plan config: %w\", err)\n}\nvar exists bool\nConn.Get(&exists, \"SELECT EXISTS(SELECT 1 FROM plans WHERE id=$1)\", planId)","typeGuard":null,"tryCatchPattern":"err := StorePlanConfig(planId, config)\nif err != nil {\n    log.Printf(\"StorePlanConfig(%s): %v\", planId, err) // inspect cause\n    http.Error(w, \"failed to save config\", http.StatusInternalServerError)\n    return\n}","preventionTips":["Check RowsAffected after the UPDATE to detect nonexistent planIds (zero rows is silent)","Run migrations with each deploy so plans.plan_config exists","Sanitize/limit the incoming PlanConfig payload before persisting","Retry once on transient connection errors before failing the request"],"tags":["database","postgres","update","sqlx","go"],"backgroundTag":"postgres-update-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"}