plandex-ai/plandex · error

Error deleting draft plans:

Error message

Error deleting draft plans: 

What it means

CreatePlanHandler returns this 500 when db.DeleteDraftPlans fails while clearing the user's existing draft plans for the project. When the requested name is "draft" (or empty), the handler first deletes prior drafts so only one draft remains; a database failure in that cleanup aborts plan creation. The DB error is appended to the message and logged.

Source

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

	var requestBody shared.CreatePlanRequest
	if err := json.Unmarshal(body, &requestBody); err != nil {
		log.Printf("Error parsing request body: %v\n", err)
		http.Error(w, "Error parsing request body", http.StatusBadRequest)
		return
	}

	name := requestBody.Name
	if name == "" {
		name = "draft"
	}

	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
			}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the server log for the underlying DeleteDraftPlans error
  2. Retry the request; transient DB or lock errors often resolve
  3. Verify database connectivity and that the plans schema migrations are applied
  4. Avoid concurrent draft creation from multiple clients/sessions for the same project
  5. If recurring, inspect for long-running transactions locking the plans table
Defensive patterns

Strategy: retry

Validate before calling

const drafts = await listPlans(projectId);
if (drafts.some(p => p.name === 'draft')) console.warn('Existing draft will be replaced');

Try / catch

for (let i = 0; i < 3; i++) {
  try {
    return await createPlan(projectId, 'draft');
  } catch (e) {
    if (i === 2 || !/Error deleting draft plans/.test(e.message)) throw e;
    await new Promise(r => setTimeout(r, 500 * 2 ** i));
  }
}

Prevention

When it happens

Trigger: POST create-plan with name "draft" where the DeleteDraftPlans(orgId, projectId, userId) DELETE query fails — database connection loss, lock contention on the plans table from concurrent draft creation, or schema/constraint errors.

Common situations: Two clients creating drafts simultaneously causing row-lock contention; Postgres outage or pool exhaustion; failed migration leaving the plans table inconsistent; replica/serialization conflicts in self-hosted setups.

Related errors


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