plandex-ai/plandex · error

Error deleting plans:

Error message

Error deleting plans: 

What it means

DeleteAllPlansHandler (plans_crud.go:286) returns 500 when db.DeleteOwnerPlans(orgId, projectId, userId) fails to delete all plans owned by the user in the project. The operation is a bulk delete (DB rows plus likely per-plan directories), so the error propagates from either the SQL execution or an internal step inside DeleteOwnerPlans.

Source

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

	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	vars := mux.Vars(r)
	projectId := vars["projectId"]

	log.Println("projectId: ", projectId)

	if !authorizeProject(w, projectId, auth) {
		return
	}

	err := db.DeleteOwnerPlans(auth.OrgId, projectId, auth.User.Id)

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

	log.Println("Successfully deleted all plans")
}

func ListPlansHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Received request for ListPlans")

	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	projectIds := r.URL.Query()["projectId"]

	log.Println("projectIds: ", projectIds)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the server log line 'Error deleting plans: <err>' to identify whether the failure is SQL-level or directory-level.
  2. Retry the request — if it's a transient connection issue, the retry should succeed and is idempotent for already-deleted plans.
  3. Check for foreign-key constraints referencing plans that block the bulk DELETE; add ON DELETE CASCADE or delete dependents first.
  4. For large projects, chunk the deletion or add a statement timeout and delete in batches.

Example fix

// before
err := db.DeleteOwnerPlans(auth.OrgId, projectId, auth.User.Id)
// after
err := db.DeleteOwnerPlansBatch(ctx, auth.OrgId, projectId, auth.User.Id, 500) // delete in batches with retry
Defensive patterns

Strategy: retry

Validate before calling

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

Type guard

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

Try / catch

err := db.DeleteOwnerPlans(auth.OrgId, projectId, auth.User.Id)
for i := 0; i < 3 && isTransientDBErr(err); i++ {
    time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
    err = db.DeleteOwnerPlans(auth.OrgId, projectId, auth.User.Id)
}

Prevention

When it happens

Trigger: POST/DELETE to the delete-all-plans route for a projectId where the underlying bulk DELETE statement errors — DB connection failure, SQL error in DeleteOwnerPlans, or an error deleting one of the plan directories inside the function.

Common situations: Database unavailable or connection pool exhausted; very large plan counts timing out; a single unreadable plan directory aborting the whole bulk operation; FK constraints if plans are referenced by other tables.

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/1b9d9512155f63e8. Report an issue: GitHub.