{"record":{"id":"44b486028ff54db7","repo":"plandex-ai/plandex","slug":"user-does-not-have-permission-to-update-plan-44b486","errorCode":null,"errorMessage":"User does not have permission to update plan","messagePattern":"User does not have permission to update plan","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"app/server/handlers/plans_exec.go","lineNumber":627,"sourceCode":"\t\tlog.Printf(\"Error marshalling response: %v\\n\", err)\n\t\thttp.Error(w, \"Error marshalling response\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Write(bytes)\n\n\t// log.Println(\"Successfully processed request for GetBuildStatusHandler\")\n}\n\nfunc authorizePlanExecUpdate(w http.ResponseWriter, planId string, auth *types.ServerAuth) *db.Plan {\n\tplan := authorizePlan(w, planId, auth)\n\tif plan == nil {\n\t\treturn nil\n\t}\n\n\tif plan.OwnerId != auth.User.Id && !auth.HasPermission(shared.PermissionUpdateAnyPlan) {\n\t\tlog.Println(\"User does not have permission to update plan\")\n\t\thttp.Error(w, \"User does not have permission to update plan\", http.StatusForbidden)\n\t\treturn nil\n\t}\n\n\treturn plan\n}\n","sourceCodeStart":609,"sourceCodeEnd":633,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_exec.go#L609-L633","documentation":"authorizePlanExecUpdate checks that the authenticated user owns the plan (plan.OwnerId == auth.User.Id) or holds the shared.PermissionUpdateAnyPlan permission. If neither holds, it writes a 403 with 'User does not have permission to update plan' and returns nil (causing callers TellPlanHandler/BuildPlanHandler to abort). It is an authorization failure, not an authentication one.","triggerScenarios":"TellPlanHandler or BuildPlanHandler is called by an authenticated user whose Id differs from plan.OwnerId and who lacks PermissionUpdateAnyPlan, at plans_exec.go:627.","commonSituations":"Team members trying to tell/build a colleague's plan without the 'update any plan' permission granted; API keys scoped to a different user; switching accounts while reusing a client with cached plan IDs.","solutions":["Verify you are operating on a plan your user owns, or log in as the owner.","Grant the user the PermissionUpdateAnyPlan permission if cross-user plan updates are intended.","Check the auth token/key actually maps to the expected user (auth.User.Id) rather than a stale session.","Confirm the planId in the request refers to the intended plan."],"exampleFix":"// before\nPOST /plans/{someoneElsesPlanId}/tell  // 403\n// after\ngrant := auth.HasPermission(shared.PermissionUpdateAnyPlan) // ask admin to enable, or use own plan\nPOST /plans/{yourPlanId}/tell","handlingStrategy":"validation","validationCode":"// client-side pre-check: only call tell/build on plans you own or have rights to\nif plan.OwnerId != currentUser.Id && !currentUser.Permissions.Contains(\"update_any_plan\") {\n    return errors.New(\"skipping: no permission to update this plan\")\n}","typeGuard":"func canUpdatePlan(p *shared.Plan, u *auth.User, has func(string) bool) bool {\n    return p != nil && (p.OwnerId == u.Id || has(shared.PermissionUpdateAnyPlan))\n}","tryCatchPattern":"resp, err := tellPlan(planId, msg)\nif err != nil {\n    var httpErr *HTTPError\n    if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusForbidden {\n        return fmt.Errorf(\"plan %s is owned by another user; request PermissionUpdateAnyPlan or use your own plan\", planId)\n    }\n    return err\n}","preventionTips":["Only send tell/build requests for plans your user owns","Request PermissionUpdateAnyPlan when team-wide plan edits are required","Verify the auth token maps to the intended user before calls","Cache plan ownership alongside plan IDs in client state"],"tags":["http","authorization","go","permissions"],"backgroundTag":"insufficient-permissions","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}