{"record":{"id":"255f6825262f1455","repo":"plandex-ai/plandex","slug":"user-does-not-have-permission-to-rename-plan","errorCode":null,"errorMessage":"User does not have permission to rename plan","messagePattern":"User does not have permission to rename plan","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"app/server/handlers/auth_helpers.go","lineNumber":730,"sourceCode":"\tif plan.OwnerId != auth.User.Id && !auth.HasPermission(shared.PermissionDeleteAnyPlan) {\n\t\tlog.Println(\"User does not have permission to delete plan\")\n\t\thttp.Error(w, \"User does not have permission to delete plan\", http.StatusForbidden)\n\t\treturn nil\n\t}\n\n\treturn plan\n}\n\nfunc authorizePlanRename(w http.ResponseWriter, planId string, auth *types.ServerAuth) *db.Plan {\n\tplan := authorizePlan(w, planId, auth)\n\n\tif plan == nil {\n\t\treturn nil\n\t}\n\n\tif plan.OwnerId != auth.User.Id && !auth.HasPermission(shared.PermissionRenameAnyPlan) {\n\t\tlog.Println(\"User does not have permission to rename plan\")\n\t\thttp.Error(w, \"User does not have permission to rename plan\", http.StatusForbidden)\n\t\treturn nil\n\t}\n\n\treturn plan\n}\n\nfunc authorizePlanArchive(w http.ResponseWriter, planId string, auth *types.ServerAuth) *db.Plan {\n\tplan := authorizePlan(w, planId, auth)\n\n\tif plan == nil {\n\t\treturn nil\n\t}\n\n\tif plan.OwnerId != auth.User.Id && !auth.HasPermission(shared.PermissionArchiveAnyPlan) {\n\t\tlog.Println(\"User does not have permission to archive plan\")\n\t\thttp.Error(w, \"User does not have permission to archive plan\", http.StatusForbidden)\n\t\treturn nil\n\t}","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/auth_helpers.go#L712-L748","documentation":"This 403 is returned by authorizePlanRename when the plan is accessible but the requester is neither the plan owner nor holds shared.PermissionRenameAnyPlan. Renaming is restricted to the owner or users with the rename-any-plan admin permission.","triggerScenarios":"A plan-rename endpoint (via authorizePlanRename) called by a non-owner member without PermissionRenameAnyPlan attempting to change the plan's title.","commonSituations":"A collaborator renames a teammate's plan from a shared view; permission revoked in a role change but client UI not refreshed; scripts using personal tokens acting on others' plans.","solutions":["Ask the plan owner to perform the rename, or obtain PermissionRenameAnyPlan","Transfer plan ownership to the user who needs rename rights","Disable rename controls for non-owners without the permission in the UI"],"exampleFix":"// before\nawait api.renamePlan(planId, 'New title');\n// after\nif (plan.ownerId !== auth.userId && !auth.permissions.includes('rename_any_plan')) {\n  throw new Error('Only the plan owner or an admin can rename this plan');\n}\nawait api.renamePlan(planId, 'New title');","handlingStrategy":"type-guard","validationCode":"function canRenamePlan(plan, auth) {\n  return plan.ownerId === auth.userId || auth.permissions.includes('rename_any_plan');\n}","typeGuard":"function isPlanOwner(plan, auth) {\n  return typeof plan?.ownerId === 'string' && plan.ownerId === auth?.userId;\n}","tryCatchPattern":"try {\n  return await api.renamePlan(planId, title);\n} catch (e) {\n  if (e.status === 403 && /permission to rename plan/.test(e.body)) {\n    notifyUser('Only the plan owner or an admin can rename this plan');\n    return null;\n  }\n  throw e;\n}","preventionTips":["Make rename inputs read-only for non-owners without the permission","Sync client permission cache after role changes","Cover rename with owner/non-owner tests","Keep plan ownership metadata in the client model for pre-checks"],"tags":["http-403","authorization","permissions","ownership"],"backgroundTag":"insufficient-permissions","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"}