plandex-ai/plandex · warning
User does not have permission to update plan
Error message
User does not have permission to update plan
What it means
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.
Source
Thrown at app/server/handlers/plans_exec.go:627
log.Printf("Error marshalling response: %v\n", err)
http.Error(w, "Error marshalling response", http.StatusInternalServerError)
return
}
w.Write(bytes)
// log.Println("Successfully processed request for GetBuildStatusHandler")
}
func authorizePlanExecUpdate(w http.ResponseWriter, planId string, auth *types.ServerAuth) *db.Plan {
plan := authorizePlan(w, planId, auth)
if plan == nil {
return nil
}
if plan.OwnerId != auth.User.Id && !auth.HasPermission(shared.PermissionUpdateAnyPlan) {
log.Println("User does not have permission to update plan")
http.Error(w, "User does not have permission to update plan", http.StatusForbidden)
return nil
}
return plan
}
View on GitHub (pinned to e2d772072e)
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.
Example fix
// before
POST /plans/{someoneElsesPlanId}/tell // 403
// after
grant := auth.HasPermission(shared.PermissionUpdateAnyPlan) // ask admin to enable, or use own plan
POST /plans/{yourPlanId}/tell Defensive patterns
Strategy: validation
Validate before calling
// client-side pre-check: only call tell/build on plans you own or have rights to
if plan.OwnerId != currentUser.Id && !currentUser.Permissions.Contains("update_any_plan") {
return errors.New("skipping: no permission to update this plan")
} Type guard
func canUpdatePlan(p *shared.Plan, u *auth.User, has func(string) bool) bool {
return p != nil && (p.OwnerId == u.Id || has(shared.PermissionUpdateAnyPlan))
} Try / catch
resp, err := tellPlan(planId, msg)
if err != nil {
var httpErr *HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusForbidden {
return fmt.Errorf("plan %s is owned by another user; request PermissionUpdateAnyPlan or use your own plan", planId)
}
return err
} Prevention
- 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
When it happens
Trigger: TellPlanHandler or BuildPlanHandler is called by an authenticated user whose Id differs from plan.OwnerId and who lacks PermissionUpdateAnyPlan, at plans_exec.go:627.
Common situations: 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.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- User does not have permission to invite user with role:
- User does not have permission to remove user with role: {org
- error walking directory: %s
- failed to check if %s exists: %s
- failed to read %s: %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/44b486028ff54db7.
Report an issue: GitHub.