plandex-ai/plandex · error
Error creating plan:
Error message
Error creating plan:
What it means
CreatePlanHandler returns this 500 when db.CreatePlan fails to insert the new plan row. The database error text is appended to the response body. The count check succeeded but the actual INSERT/update of plan state failed.
Source
Thrown at app/server/handlers/plans_crud.go:107
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
}
resp := shared.CreatePlanResponse{
Id: plan.Id,
Name: plan.Name,
}
bytes, err := json.Marshal(resp)
if err != nil {
log.Printf("Error marshalling response: %v\n", err)
http.Error(w, "Error marshalling response: "+err.Error(), http.StatusInternalServerError)
return
}
w.Write(bytes)
View on GitHub (pinned to e2d772072e)
Solutions
- Read the wrapped database error in the response body/server log (e.g. unique violation vs context canceled)
- Retry the request if it was a transient connection error or a name-collision race (the suffix loop will pick the next name)
- Verify the project still exists and the user belongs to the org before calling
- Check Postgres health: disk space, connection limits, and that the transaction wasn't rolled back by serialization failure
Example fix
// before
plan, err := db.CreatePlan(r.Context(), auth.OrgId, projectId, auth.User.Id, name)
if err != nil { http.Error(w, "Error creating plan: "+err.Error(), http.StatusInternalServerError); return }
// after
plan, err := db.CreatePlan(r.Context(), auth.OrgId, projectId, auth.User.Id, name)
if err != nil {
if r.Context().Err() != nil { return } // client gone, don't log as server error
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) && pgErr.Code == "23505" { name = name + ".2"; /* retry once */ }
} Defensive patterns
Strategy: retry
Validate before calling
if r.Context().Err() != nil { return } // don't attempt insert after client cancelled Type guard
func isUniqueViolation(err error) bool { var pgErr *pgconn.PgError; return errors.As(err, &pgErr) && pgErr.Code == "23505" } Try / catch
plan, err := db.CreatePlan(r.Context(), orgId, projectId, userId, name)
if err != nil {
if isUniqueViolation(err) { /* retry with suffixed name */ }
if isTransientDBErr(err) { /* retry with backoff */ }
http.Error(w, "Error creating plan", http.StatusInternalServerError)
return
} Prevention
- Add a unique constraint plus retry-on-23505 to make name races deterministic
- Use the request context so cancelled requests abort cleanly
- Verify foreign keys (project, user) exist before insert in tests
- Monitor disk space and connection saturation on the database host
When it happens
Trigger: POST create-plan call where db.CreatePlan(r.Context(), orgId, projectId, userId, name) fails: foreign-key violation (project or user row missing), unique constraint race on the name suffix, context cancelled by the client, or DB connection loss during the write.
Common situations: Client disconnects mid-request cancelling the context; two concurrent creates racing past the COUNT check onto a unique index; project deleted between authorization and insert; Postgres disk full or read-only replica promoted incorrectly.
Related errors
- error adding org member: %v
- error adding org user: %v
- Error checking if plan exists:
- Error renaming plan:
- Error deleting plan:
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/6c17b583af34ebaa.
Report an issue: GitHub.