plandex-ai/plandex · error
Error listing projects:
Error message
Error listing projects:
What it means
ListProjectsHandler issues 'SELECT id, name FROM projects WHERE org_id = $1' against the shared db.Conn. Any error returned by database/sql Query — connection failure, bad SQL, missing table — is logged and returned as HTTP 500 with the driver's error text appended.
Source
Thrown at app/server/handlers/projects.go:96
w.Write(bytes)
log.Println("Successfully created project", projectId)
}
func ListProjectsHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for ListProjectsHandler")
auth := Authenticate(w, r, true)
if auth == nil {
return
}
rows, err := db.Conn.Query("SELECT id, name FROM projects WHERE org_id = $1", auth.OrgId)
if err != nil {
log.Printf("Error listing projects: %v\n", err)
http.Error(w, "Error listing projects: "+err.Error(), http.StatusInternalServerError)
return
}
var projects []shared.Project
for rows.Next() {
var project shared.Project
err := rows.Scan(&project.Id, &project.Name)
if err != nil {
log.Printf("Error scanning project: %v\n", err)
http.Error(w, "Error scanning project: "+err.Error(), http.StatusInternalServerError)
return
}
projects = append(projects, project)
}
bytes, err := json.Marshal(projects)
if err != nil {View on GitHub (pinned to e2d772072e)
Solutions
- Read the appended driver error: 'connection refused' means DB is down/wrong host; 'relation "projects" does not exist' means run migrations.
- Verify Postgres is running and reachable from the server (psql with the same DSN).
- Check env/DSN configuration (host, port, user, password, dbname) for typos.
- Ensure migrations creating the projects table have been applied.
- If pool exhaustion, raise max_connections or fix leaked rows (note: this handler never calls rows.Close(), which can leak connections under load).
Example fix
// before
rows, err := db.Conn.Query("SELECT id, name FROM projects WHERE org_id = $1", auth.OrgId)
...
// after
rows, err := db.Conn.Query("SELECT id, name FROM projects WHERE org_id = $1", auth.OrgId)
if err != nil { ... }
defer rows.Close() Defensive patterns
Strategy: retry
Validate before calling
if err := db.Conn.PingContext(ctx); err != nil {
return fmt.Errorf("database unavailable: %w", err)
} Try / catch
projects, err := client.ListProjects(ctx)
if err != nil {
var apiErr *APIError
if errors.As(err, &apiErr) && apiErr.StatusCode == 500 {
return retryWithBackoff(ctx, 3, func() error { _, err = client.ListProjects(ctx); return err })
}
return err
} Prevention
- Add readiness/liveness probes that ping the database before serving traffic.
- Apply migrations as part of deployment before the server starts.
- Pool connections properly (always defer rows.Close()) to avoid exhaustion.
- Alert on DB error rates; distinguish connection-refused from SQL errors in logs.
- Use a DSN from env with validated defaults and connection timeout settings.
When it happens
Trigger: GET/POST to the list-projects endpoint after successful auth, when the DB query fails: Postgres unreachable, connection pool exhausted, projects table missing, or syntax/permission error on the query.
Common situations: Postgres down or restarted; wrong DATABASE_URL in server env; migrations not applied; too many open connections (max_connections exceeded); TLS/cert misconfiguration between server and DB.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Error updating project:
- error creating plan: %v
- error inserting lockable plan id: %v
- error listing plans: %v
- error updating user num_non_draft_plans: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/ade02a547dab2155.
Report an issue: GitHub.