{"record":{"id":"6d417090dd29763e","repo":"calcom/cal.diy","slug":"rolesguard-user-with-id-user-id-does-not-have","errorCode":null,"errorMessage":"RolesGuard - user with id=${user.id} does not have the minimum required role=${allowedRole} within","messagePattern":"RolesGuard - user with id=(.+?) does not have the minimum required role=(.+?) within","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"apps/api/v2/src/modules/auth/guards/roles/roles.guard.ts","lineNumber":50,"sourceCode":"\n    if (!canAccess) {\n      this.throwForbiddenError(user, orgId, teamId, allowedRole);\n    }\n\n    return true;\n  }\n\n  throwForbiddenError(user: ApiAuthGuardUser, orgId: string, teamId: string, allowedRole: string) {\n    let errorMessage = `RolesGuard - user with id=${user.id} does not have the minimum required role=${allowedRole} within`;\n    if (orgId) {\n      errorMessage += ` organization with id=${orgId}`;\n    }\n    if (teamId) {\n      errorMessage += ` team with id=${teamId}`;\n    }\n    errorMessage += `.`;\n\n    throw new ForbiddenException(errorMessage);\n  }\n\n  async checkUserRoleAccess(\n    user: ApiAuthGuardUser,\n    orgId: string,\n    teamId: string,\n    allowedRole: string\n  ): Promise<{ canAccess: boolean }> {\n    const REDIS_CACHE_KEY = `apiv2:user:${user.id ?? \"none\"}:org:${orgId ?? \"none\"}:team:${\n      teamId ?? \"none\"\n    }:guard:roles:${allowedRole}`;\n    const cachedAccess = JSON.parse((await this.redisService.redis.get(REDIS_CACHE_KEY)) ?? \"false\");\n\n    if (cachedAccess) {\n      return { canAccess: cachedAccess };\n    }\n\n    let canAccess = false;","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/auth/guards/roles/roles.guard.ts#L32-L68","documentation":"ForbiddenException from RolesGuard.throwForbiddenError — built dynamically to state that the authenticated user lacks the minimum required role within a specific organization and/or team. The message appends the org and/or team id depending on which scope was requested. Role checks use hasMinimumRole against ORG_ROLES / TEAM_ROLES hierarchies.","triggerScenarios":"Calling a @Roles(...) / @MinimumRole(...) guarded endpoint where the user's membership role in the target org/team is below the allowed role — e.g. an ORG_MEMBER calling a route that requires ORG_ADMIN, or a TEAM_MEMBER calling a route requiring TEAM_OWNER.","commonSituations":"Promoting a user is pending/awaiting acceptance; user is a member of the parent org but not with a sufficient role; test fixtures assign the wrong role; team-only route called by an org-only admin where org-above-team escalation does not apply; SYSTEM_ADMIN_ROLE route hit by a non-system-admin.","solutions":["Have an org owner/admin promote the user to the required role in the Cal.com dashboard.","Verify the request targets the correct orgId/teamId — the user may be sufficiently privileged in a different team.","For SYSTEM_ADMIN_ROLE routes, confirm the user has the system admin flag in the database.","Clear the Redis cache key apiv2:user:<id>:org:<orgId>:team:<teamId>:guard:roles:<role> if roles were just changed and the cached 'false' is stale."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const allowed = ['ORG_ADMIN'];\nconst userRole = membership.role; // 'MEMBER' | 'ADMIN' | 'OWNER' | ...\nconst ok = hasMinimumRole({ checkRole: `ORG_${userRole}`, minimumRole: allowed[0], roles: ORG_ROLES });\nif (!ok) { /* tell user they need elevation */ }","typeGuard":null,"tryCatchPattern":"try {\n  await client.get(`/v2/orgs/${orgId}/settings`);\n} catch (e) {\n  if (e.status === 403 && /does not have the minimum required role/.test(e.message)) {\n    // prompt user to request role elevation from an owner\n  }\n  throw e;\n}","preventionTips":["After elevating a user, clear the apiv2:user:…:guard:roles: Redis cache or wait it out.","Verify you are operating on the right orgId/teamId.","Seed Membership rows correctly in tests."],"tags":["auth","roles","rbac","organization","team","guard"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}