{"record":{"id":"dc63472776bc1406","repo":"plandex-ai/plandex","slug":"error-renaming-plan","errorCode":null,"errorMessage":"Error renaming plan: ","messagePattern":"Error renaming plan: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_crud.go","lineNumber":201,"sourceCode":"\t}\n\n\tif plan.OwnerId != auth.User.Id {\n\t\tlog.Println(\"Only the plan owner can rename a plan\")\n\t\thttp.Error(w, \"Only the plan owner can rename a plan\", http.StatusForbidden)\n\t\treturn\n\t}\n\n\tif requestBody.Name == \"\" {\n\t\tlog.Println(\"Name cannot be empty\")\n\t\thttp.Error(w, \"Name cannot be empty\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\terr := db.RenamePlan(planId, requestBody.Name, nil)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error renaming plan: %v\\n\", err)\n\t\thttp.Error(w, \"Error renaming plan: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlog.Println(\"Successfully renamed plan\")\n}\n\nfunc DeletePlanHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for DeletePlanHandler\")\n\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tvars := mux.Vars(r)\n\tplanId := vars[\"planId\"]\n\n\tlog.Println(\"planId: \", planId)","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_crud.go#L183-L219","documentation":"RenamePlanHandler returns this 500 when db.RenamePlan fails to persist the new name. Ownership and name validation passed, but the database update errored; the underlying error text is appended to the response. Note the third argument nil suggests an optional tx/lock parameter that can influence behavior.","triggerScenarios":"POST rename passing validation but db.RenamePlan(planId, requestBody.Name, nil) fails: DB connection loss, statement timeout, plans row deleted concurrently between authorizePlan and the update, unique constraint on (project_id, owner_id, name), or lock contention with an active plan operation.","commonSituations":"Postgres restart/failover mid-request; plan deleted by another session during the rename; renaming to a name that already exists for the same owner+project hitting a unique index; long-running lock held by an active generation stream.","solutions":["Inspect the wrapped database error in the response body/server log to classify the failure","Retry the rename if it was transient (connection reset) or pick a different name on unique violation","Confirm the plan still exists (it may have been deleted concurrently) — the response 404 vs 500 will clarify","Check for lock contention with active plan sessions and retry after they finish"],"exampleFix":"// before\nerr := db.RenamePlan(planId, requestBody.Name, nil)\n// after\nerr := db.RenamePlan(planId, requestBody.Name, nil)\nif err != nil {\n\tvar pgErr *pgconn.PgError\n\tif errors.As(err, &pgErr) && pgErr.Code == \"23505\" {\n\t\thttp.Error(w, \"A plan with that name already exists\", http.StatusConflict); return\n\t}\n\t\n}","handlingStrategy":"retry","validationCode":"if _, err := db.Conn.Exec(\"SELECT 1 FROM plans WHERE id=$1\", planId); err != nil { return err } // row still exists","typeGuard":"func isUniqueViolation(err error) bool { var pgErr *pgconn.PgError; return errors.As(err, &pgErr) && pgErr.Code == \"23505\" }","tryCatchPattern":"err := db.RenamePlan(planId, requestBody.Name, nil)\nif err != nil {\n\tif isUniqueViolation(err) { http.Error(w, \"name already in use\", http.StatusConflict); return }\n\tif isTransientDBErr(err) { /* retry with backoff */ return }\n\thttp.Error(w, \"Error renaming plan\", http.StatusInternalServerError)\n\treturn\n}","preventionTips":["Map unique-violation errors to 409 responses instead of generic 500","Use short timeouts and retry transient connection errors with backoff","Check the plan still exists before/after rename to avoid races with deletes","Avoid renaming while a generation stream holds locks on the plan row"],"tags":["database","update","postgres","server-error"],"backgroundTag":"database-query-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}