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, nil

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped %v detail; if it's a scan/columns mismatch, run pending migrations or redeploy the matching server version
  2. Check database connectivity and pool health; retry on transient connection errors
  3. Ensure the caller passes a non-nil projectIds slice; if empty, short-circuit to return an empty list instead of querying
  4. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/6e974e0e7af741e0. Report an issue: GitHub.