plandex-ai/plandex · error
error listing plans: %v
Error message
error listing plans: %v
What it means
This error wraps a failure of Conn.Select(&plans, qs, qargs...) in ListOwnedPlans (app/server/db/plan_helpers.go:113). The function queries all plans for a set of project ids owned by a user, filtered by archived status, using sqlx Select to scan rows directly into []*Plan. It surfaces SQL execution errors and row-scan/destination mapping errors alike.
Source
Thrown at app/server/db/plan_helpers.go:113
}
func ListOwnedPlans(projectIds []string, userId string, archived bool) ([]*Plan, error) {
qs := "SELECT * FROM plans WHERE project_id = ANY($1) AND owner_id = $2"
qargs := []interface{}{pq.Array(projectIds), userId}
if archived {
qs += " AND archived_at IS NOT NULL"
} else {
qs += " AND archived_at IS NULL"
}
qs += " ORDER BY updated_at DESC"
var plans []*Plan
err := Conn.Select(&plans, qs, qargs...)
if err != nil {
return nil, fmt.Errorf("error listing plans: %v", err)
}
return plans, nil
}
func GetPlanNamesById(planIds []string) (map[string]string, error) {
var plans []*Plan
err := Conn.Select(&plans, "SELECT id, name FROM plans WHERE id = ANY($1)", pq.Array(planIds))
if err != nil {
return nil, fmt.Errorf("error getting plan names: %v", err)
}
namesMap := make(map[string]string)
for _, plan := range plans {
namesMap[plan.Id] = plan.Name
}
return namesMap, nilView on GitHub (pinned to e2d772072e)
Solutions
- Read the wrapped %v detail; if it's a scan/columns mismatch, run pending migrations or redeploy the matching server version
- Check database connectivity and pool health; retry on transient connection errors
- Ensure the caller passes a non-nil projectIds slice; if empty, short-circuit to return an empty list instead of querying
- If SELECT * keeps breaking on schema changes, enumerate explicit columns in the query so scans stay stable
Example fix
// before
qs := "SELECT * FROM plans WHERE project_id = ANY($1) AND owner_id = $2"
// after (explicit columns survive schema drift; guard empty input)
if len(projectIds) == 0 {
return []*Plan{}, nil
}
qs := "SELECT id, org_id, owner_id, project_id, name, plan_config, archived_at, shared_with_org_at, created_at, updated_at FROM plans WHERE project_id = ANY($1) AND owner_id = $2" Defensive patterns
Strategy: retry
Validate before calling
// Go: pre-flight before ListOwnedPlans
if projectIds == nil {
projectIds = []string{}
}
if err := Conn.PingContext(ctx); err != nil {
return fmt.Errorf("database unreachable: %w", err)
} Type guard
func isRetryableDBError(err error) bool {
var pqErr *pq.Error
if errors.As(err, &pqErr) {
switch pqErr.Code {
case "08006", "08001", "57P01", "53300": // connection failures, admin shutdown, too many connections
return true
}
return false
}
return errors.Is(err, context.DeadlineExceeded)
} Try / catch
plans, err := db.ListOwnedPlans(projectIds, userId, archived)
if err != nil {
if isRetryableDBError(err) {
plans, err = retryWithBackoff(3, time.Second, func() ([]*db.Plan, error) {
return db.ListOwnedPlans(projectIds, userId, archived)
})
}
if err != nil {
http.Error(w, "could not load plans", http.StatusInternalServerError)
return
}
} Prevention
- Keep the Plan struct and DB schema in sync; run migrations on every deploy
- Prefer explicit column lists over SELECT * to survive schema drift
- Set sane connection-pool limits and monitor pool exhaustion (53300)
- Guard empty projectIds input at the handler layer before querying
When it happens
Trigger: Called by ListPlansHandler, ListArchivedPlansHandler, ListPlansRunningHandler, and GetCurrentBranchByPlanIdHandler; fails when the plans table is missing or altered (SELECT * columns no longer match the Plan struct), when the database connection is down, when projectIds is invalid for pq.Array, or when a scan target type mismatches a column type after a migration.
Common situations: Deployed code newer than the DB schema (or vice versa) so SELECT * columns don't match Plan fields, transient Postgres connection failures, empty projectIds slice producing unexpected array binding, or connection-pool exhaustion under load.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- error getting invite: %v
- error listing org roles: %v
- error creating plan: %v
- error inserting lockable plan id: %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/6e974e0e7af741e0.
Report an issue: GitHub.