{"record":{"id":"b4f9c27eb0e778cb","repo":"plandex-ai/plandex","slug":"error-listing-plans","errorCode":null,"errorMessage":"Error listing plans: ","messagePattern":"Error listing plans: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_crud.go","lineNumber":339,"sourceCode":"\t}\n\n\tauthorizedProjectIds := []string{}\n\tfor _, projectId := range projectIds {\n\t\tif authorizeProjectOptional(w, projectId, auth, false) {\n\t\t\tauthorizedProjectIds = append(authorizedProjectIds, projectId)\n\t\t}\n\t}\n\n\tif len(authorizedProjectIds) == 0 {\n\t\twritePlans()\n\t\treturn\n\t}\n\n\tplans, err := db.ListOwnedPlans(authorizedProjectIds, auth.User.Id, false)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error listing plans: %v\\n\", err)\n\t\thttp.Error(w, \"Error listing plans: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tfor _, plan := range plans {\n\t\tapiPlans = append(apiPlans, plan.ToApi())\n\t}\n\n\twritePlans()\n}\n\nfunc ListArchivedPlansHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for ListArchivedPlansHandler\")\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tprojectIds := r.URL.Query()[\"projectId\"]","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_crud.go#L321-L357","documentation":"ListPlansHandler (plans_crud.go:339) returns 500 when db.ListOwnedPlans(authorizedProjectIds, userId, false) fails to query the user's plans for the authorized projects. The error originates in the database layer — connection failure, SQL error, or scan error while reading rows.","triggerScenarios":"GET /plans?projectId=... with at least one authorized projectId, and the ListOwnedPlans SQL query fails: DB unreachable, connection pool exhausted, invalid query after a schema migration (renamed columns/table), or row-scan type mismatch.","commonSituations":"Database restart or network blip; deploying code against a mismatched schema (migration not applied); connection pool exhaustion under load; listing plans for many projects producing a query timeout.","solutions":["Check the server log 'Error listing plans: <err>' for the underlying DB error and fix accordingly.","Verify DB connectivity/pool health (max connections, idle timeouts) and that the DB is running.","Confirm the plans schema matches the deployed code — run pending migrations.","Retry the request for transient failures; add automatic retry with backoff for idempotent reads."],"exampleFix":"// before\nplans, err := db.ListOwnedPlans(authorizedProjectIds, auth.User.Id, false)\n// after\nplans, err := db.ListOwnedPlans(authorizedProjectIds, auth.User.Id, false)\nif err != nil {\n    if isTransient(err) { // e.g. pgconn.SafeToRetry\n        plans, err = db.ListOwnedPlans(authorizedProjectIds, auth.User.Id, false)\n    }\n}","handlingStrategy":"retry","validationCode":"if len(authorizedProjectIds) == 0 { return } // caller already guards this before querying\nif err := db.Conn.PingContext(ctx); err != nil { return err }","typeGuard":"func isTransientDBErr(err error) bool {\n    var pgErr *pgconn.PgError\n    return errors.As(err, &pgErr) && pgconn.SafeToRetry(err)\n}","tryCatchPattern":"plans, err := db.ListOwnedPlans(ids, userId, false)\nif err != nil {\n    if isTransientDBErr(err) {\n        plans, err = db.ListOwnedPlans(ids, userId, false) // one bounded retry\n    }\n    if err != nil {\n        http.Error(w, \"Error listing plans\", http.StatusInternalServerError)\n        return\n    }\n}","preventionTips":["Apply DB migrations before deploying schema-dependent code.","Monitor pool saturation; size max connections for read-heavy list endpoints.","Retry idempotent reads on transient errors with backoff.","Alert on database connection/error rate from handler logs."],"tags":["database","go","http-500","query-failure"],"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"}