{"record":{"id":"053dc8b7c34005fe","repo":"plandex-ai/plandex","slug":"error-archiving-plan","errorCode":null,"errorMessage":"Error archiving plan: ","messagePattern":"Error archiving plan: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_changes.go","lineNumber":460,"sourceCode":"\tlog.Println(\"planId: \", planId)\n\n\tplan := authorizePlanArchive(w, planId, auth)\n\n\tif plan == nil {\n\t\treturn\n\t}\n\n\tif plan.ArchivedAt != nil {\n\t\tlog.Println(\"Plan already archived\")\n\t\thttp.Error(w, \"Plan already archived\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tres, err := db.Conn.Exec(\"UPDATE plans SET archived_at = NOW() WHERE id = $1\", planId)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error archiving plan: %v\\n\", err)\n\t\thttp.Error(w, \"Error archiving plan: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\trowsAffected, err := res.RowsAffected()\n\tif err != nil {\n\t\tlog.Printf(\"Error getting rows affected: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting rows affected: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tif rowsAffected == 0 {\n\t\tlog.Println(\"Plan not found\")\n\t\thttp.Error(w, \"Not found\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tlog.Println(\"Successfully archived plan\", planId)\n}","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_changes.go#L442-L478","documentation":"The SQL UPDATE setting plans.archived_at = NOW() failed at the database level, and the handler returns HTTP 500 with 'Error archiving plan: <err>'. This indicates a DB-level problem, not a client payload problem.","triggerScenarios":"db.Conn.Exec('UPDATE plans SET archived_at = NOW() WHERE id = $1', planId) errors: database unreachable, connection pool exhausted, permission denied on UPDATE, table/schema drift (archived_at column missing), or query timeout.","commonSituations":"Postgres restarted or network blip between app and DB; migration not applied so archived_at column doesn't exist; app DB user lacks UPDATE privilege on plans; pool saturation under load.","solutions":["Read the appended err.Error() — it names the exact Postgres failure","Check DB connectivity/health and app logs around the timestamp","Verify the archived_at column exists (run pending migrations)","Confirm the app's DB role has UPDATE on plans; retry once connectivity is restored"],"exampleFix":"-- if schema drift is the cause\nALTER TABLE plans ADD COLUMN IF NOT EXISTS archived_at TIMESTAMPTZ;","handlingStrategy":"retry","validationCode":"if (!planId) throw new Error('planId required');\nconst plan = await getPlan(planId); // fail early if plan/DB unreachable\nif (plan.archivedAt) throw new Error('already archived');","typeGuard":"function isDbConnectivityError(msg) { return /connection refused|dial tcp|too many connections|timeout/i.test(msg); }","tryCatchPattern":"try { await archivePlan(planId); } catch (e) { if (e.status === 500 && isDbConnectivityError(e.message)) await retryWithBackoff(() => archivePlan(planId)); else throw e; }","preventionTips":["Monitor DB health; alert on connection/pool exhaustion","Keep schema migrations applied (archived_at column must exist)","Grant the app role UPDATE on plans","Only retry transient-looking 500s (connectivity/timeout), not permission errors"],"tags":["database","postgresql","sql","internal-server-error","go"],"backgroundTag":"database-query-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"}