calcom/cal.diy · error · ForbiddenException
RolesGuard - User is not a member of the organization with i
Error message
RolesGuard - User is not a member of the organization with id=${orgId}. What it means
ForbiddenException from RolesGuard when checking role access for an org-scoped (orgId present, teamId absent) request and membershipRepository.findMembershipByOrgId(orgId, user.id) returns null — the user is not a member of that organization at all, so role comparison is skipped and a hard 403 is thrown.
Source
Thrown at apps/api/v2/src/modules/auth/guards/roles/roles.guard.ts:93
// System admin can access everything
else if (user.isSystemAdmin) {
this.logger.log(`User (${user.id}) is system admin, allowing access.`);
canAccess = true;
}
// if the required role is SYSTEM_ADMIN_ROLE but user is not system admin, return false
else if (allowedRole === SYSTEM_ADMIN_ROLE && !user.isSystemAdmin) {
this.logger.log(`User (${user.id}) is not system admin, denying access.`);
canAccess = false;
}
// Checking the role of the user within the organization
else if (Boolean(orgId) && !Boolean(teamId)) {
const membership = await this.membershipRepository.findMembershipByOrgId(Number(orgId), user.id);
if (!membership) {
this.logger.log(`User (${user.id}) is not a member of the organization (${orgId}), denying access.`);
throw new ForbiddenException(
`RolesGuard - User is not a member of the organization with id=${orgId}.`
);
}
if (ORG_ROLES.includes(allowedRole as unknown as (typeof ORG_ROLES)[number])) {
canAccess = hasMinimumRole({
checkRole: `ORG_${membership.role}`,
minimumRole: allowedRole,
roles: ORG_ROLES,
});
}
}
// Checking the role of the user within the team
else if (Boolean(teamId) && !Boolean(orgId)) {
const membership = await this.membershipRepository.findMembershipByTeamId(Number(teamId), user.id);
if (!membership) {
this.logger.log(`User (${user.id}) is not a member of the team (${teamId}), denying access.`);View on GitHub (pinned to 176037d0af)
Solutions
- Have an org admin invite the user and have the user accept the invitation.
- Confirm the orgId in the request matches an org the user actually belongs to.
- If the user was just added, the RolesGuard Redis cache (apiv2:user:…:guard:roles:…) may hold a stale 'false' — clear it.
- For tests, seed a Membership row for the user in that org.
Defensive patterns
Strategy: validation
Validate before calling
const membership = await membershipRepository.findMembershipByOrgId(Number(orgId), user.id);
if (!membership) {
// prompt user to accept an org invitation before calling
} Try / catch
try {
await client.get(`/v2/orgs/${orgId}/teams`);
} catch (e) {
if (e.status === 403 && /not a member of the organization/.test(e.message)) {
// ask user to join the org
}
throw e;
} Prevention
- Ensure the user has accepted the org invitation.
- Confirm the orgId is correct for the user's tenant.
- Clear the RolesGuard Redis cache after membership changes.
When it happens
Trigger: Calling an org-scoped route (orgId set, no teamId) where the authenticated user has no Membership row linking them to that organization. The guard logs 'User (id) is not a member of the organization' before throwing.
Common situations: User was removed from the org; invitation never accepted; orgId typo/mismatch; cross-tenant access attempted; user belongs to a team inside a different org; test user not seeded into the org.
Related errors
- RolesGuard - User is not part of the organization with id=${
- RolesGuard - User is not part of the team with id=${teamId}
- RolesGuard - user with id=${user.id} does not have the minim
- RolesGuard - User is not a member of the team with id=${team
- GetOrgId decorator: Organization ID not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/966d72d82b25a605.
Report an issue: GitHub.