plandex-ai/plandex · error

Error checking if plan exists:

Error message

Error checking if plan exists: 

What it means

CreatePlanHandler returns this 500 when the sqlx query that counts existing plans with the same project_id/owner_id/name fails. It is part of the duplicate-name auto-suffix loop, so the handler cannot proceed to create the plan. It surfaces the underlying database error text in the response body.

Source

Thrown at app/server/handlers/plans_crud.go:90

	if name == "draft" {
		// delete any existing draft plans
		err = db.DeleteDraftPlans(auth.OrgId, projectId, auth.User.Id)

		if err != nil {
			log.Printf("Error deleting draft plans: %v\n", err)
			http.Error(w, "Error deleting draft plans: "+err.Error(), http.StatusInternalServerError)
			return
		}
	} else {
		i := 2
		originalName := name
		for {
			var count int
			err := db.Conn.Get(&count, "SELECT COUNT(*) FROM plans WHERE project_id = $1 AND owner_id = $2 AND name = $3", projectId, auth.User.Id, name)

			if err != nil {
				log.Printf("Error checking if plan exists: %v\n", err)
				http.Error(w, "Error checking if plan exists: "+err.Error(), http.StatusInternalServerError)
				return
			}

			if count == 0 {
				break
			}

			name = originalName + "." + fmt.Sprint(i)
			i++
		}
	}

	plan, err := db.CreatePlan(r.Context(), auth.OrgId, projectId, auth.User.Id, name)

	if err != nil {
		log.Printf("Error creating plan: %v\n", err)
		http.Error(w, "Error creating plan: "+err.Error(), http.StatusInternalServerError)
		return

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check server logs for the wrapped database error text appended after the prefix to identify the root cause
  2. Verify the Postgres instance is reachable and DATABASE_URL is correct (try psql with the same DSN)
  3. Run migrations to ensure the plans table exists with project_id, owner_id and name columns
  4. Check connection pool settings/limits (max conns, idle timeout) and restart saturated database connections

Example fix

// before
err := db.Conn.Get(&count, "SELECT COUNT(*) FROM plans WHERE project_id = $1 AND owner_id = $2 AND name = $3", projectId, auth.User.Id, name)
// after
if db.Conn == nil { http.Error(w, "database not initialized", http.StatusInternalServerError); return }
err := db.Conn.Get(&count, "SELECT COUNT(*) FROM plans WHERE project_id = $1 AND owner_id = $2 AND name = $3", projectId, auth.User.Id, name)
Defensive patterns

Strategy: retry

Validate before calling

if err := db.Conn.Ping(); err != nil { return fmt.Errorf("database unreachable: %w", err) }

Type guard

func isDBError(err error) bool { var pgErr *pgconn.PgError; return errors.As(err, &pgErr) }

Try / catch

if err := db.Conn.Get(&count, q, args...); err != nil {
	if isTransientDBErr(err) { /* backoff and retry once */ }
	log.Printf("Error checking if plan exists: %v\n", err)
	http.Error(w, "Error checking if plan exists", http.StatusInternalServerError)
	return
}

Prevention

When it happens

Trigger: POST to create a plan with a non-empty name (not 'draft') while db.Conn.Get on the plans table errors: plans table missing/migrated differently, database unreachable, connection pool exhausted, or a schema/type mismatch binding the count into int.

Common situations: Postgres not running or wrong DATABASE_URL after a deploy; partial migration leaving plans table columns missing (e.g. owner_id); DB connection dropped mid-request (TLS timeout, restart); replica failover.

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


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