{"record":{"id":"d2bf10a53c8b6e65","repo":"plandex-ai/plandex","slug":"user-does-not-have-permission-to-invite-user-with","errorCode":null,"errorMessage":"User does not have permission to invite user with role: ","messagePattern":"User does not have permission to invite user with role: ","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"app/server/handlers/invites.go","lineNumber":70,"sourceCode":"\t}\n\n\tcurrentUserId := auth.User.Id\n\n\tvar req shared.InviteRequest\n\terr = json.NewDecoder(r.Body).Decode(&req)\n\tif err != nil {\n\t\tlog.Printf(\"Error unmarshalling request: %v\\n\", err)\n\t\thttp.Error(w, \"Error unmarshalling request: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\treq.Email = strings.ToLower(req.Email)\n\n\t// ensure current user can invite target user\n\tpermission := shared.Permission(strings.Join([]string{string(shared.PermissionInviteUser), req.OrgRoleId}, \"|\"))\n\n\tif !auth.HasPermission(permission) {\n\t\tlog.Printf(\"User does not have permission to invite user with role: %v\\n\", req.OrgRoleId)\n\t\thttp.Error(w, \"User does not have permission to invite user with role: \"+req.OrgRoleId, http.StatusForbidden)\n\t\treturn\n\t}\n\n\t// ensure user doesn't already have access to org via domain\n\tsplit := strings.Split(req.Email, \"@\")\n\tif len(split) != 2 {\n\t\tlog.Printf(\"Invalid email: %v\\n\", req.Email)\n\t\thttp.Error(w, \"Invalid email: \"+req.Email, http.StatusBadRequest)\n\t\treturn\n\t}\n\tdomain := &split[1]\n\n\tif org.AutoAddDomainUsers && org.Domain == domain {\n\t\tlog.Printf(\"User already has access to org via domain: %v\\n\", domain)\n\t\thttp.Error(w, \"User already has access to org via domain: \"+*domain, http.StatusBadRequest)\n\t}\n\n\t// ensure user with this email isn't already in the org","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/invites.go#L52-L88","documentation":"Before creating an invite, the handler composes the permission 'invite_user|<orgRoleId>' and checks it with auth.HasPermission. If the authenticated user lacks that role-scoped invite permission, the handler responds 403 with this message naming the requested OrgRoleId.","triggerScenarios":"Inviting a user while specifying an OrgRoleId the caller is not allowed to assign invites for — e.g. a member/developer-only user trying to invite someone as an admin, or passing an unknown/garbage OrgRoleId that no permission grants cover.","commonSituations":"Non-admin users attempting to invite admins; the client sending a hardcoded or stale orgRoleId (renamed or deleted role); trial or restricted org plans; API calls with a token belonging to a lower-privileged account than assumed.","solutions":["Verify the caller's role grants the 'invite_user|<orgRoleId>' permission; use an account with admin/owner rights or a role you are permitted to invite into","Confirm req.OrgRoleId is the correct current role ID (fetch org roles from the API rather than hardcoding)","Ask an org admin to grant your role the invite permission for the target role, or have an admin perform the invite","Check you are authenticated with the intended account/token and not a personal vs org token mismatch"],"exampleFix":"// before\n{ \"email\": \"dev@example.com\", \"orgRoleId\": \"admin\" }   // caller is a plain member\n// after\n{ \"email\": \"dev@example.com\", \"orgRoleId\": \"developer\" } // role the caller may invite into, or run as an admin","handlingStrategy":"type-guard","validationCode":"// Before inviting, confirm the caller can invite into the target role\n// e.g. fetch my role's permissions and check for 'invite_user|<orgRoleId>'\nperms, err := client.GetMyPermissions(ctx)\nif err != nil {\n    return err\n}\nwanted := \"invite_user|\" + orgRoleID\nif !slices.Contains(perms, wanted) {\n    return fmt.Errorf(\"caller lacks permission %s — ask an admin or pick a permitted role\", wanted)\n}","typeGuard":"func canInvite(perms []string, orgRoleID string) bool {\n    wanted := \"invite_user|\" + orgRoleID\n    return slices.Contains(perms, wanted)\n}","tryCatchPattern":"err := client.InviteUser(ctx, email, orgRoleID)\nif err != nil && strings.Contains(err.Error(), \"does not have permission to invite\") {\n    return fmt.Errorf(\"forbidden: cannot invite into role %s — escalate to an org admin\", orgRoleID)\n}","preventionTips":["Fetch valid org role IDs from the API instead of hardcoding them","Check the caller's role-scoped invite permission before calling","Don't attempt admin-role invites from non-admin accounts","Handle 403 distinctly from 5xx so users see an actionable message"],"tags":["auth","permissions","authorization","http"],"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"}