calcom/cal.diy · error · UnauthorizedException

ApiAuthStrategy - next auth - Email not found in the authent

Error message

ApiAuthStrategy - next auth - Email not found in the authentication token.

What it means

Thrown by ApiAuthStrategy.nextAuthStrategy when the decoded NextAuth JWT has no `email` claim. The guard took the next-auth path (Bearer that is not an API key and not an OAuth access token) and decoded a session token, but the resulting payload lacks an email — Cal.com keys users by email, so it cannot resolve the principal.

Source

Thrown at apps/api/v2/src/modules/auth/strategies/api-auth/api-auth.strategy.ts:303

      );
    }

    const user: UserWithProfile | null = await this.userRepository.findByIdWithProfile(ownerId);
    if (!user) {
      throw new UnauthorizedException(
        "ApiAuthStrategy - access token - User associated with the access token not found."
      );
    }

    const organizationId = this.usersService.getUserMainOrgId(user) as number;
    request.organizationId = organizationId;

    return user;
  }

  async nextAuthStrategy(token: { email?: string | null }, request: ApiAuthGuardRequest) {
    if (!token.email) {
      throw new UnauthorizedException(
        "ApiAuthStrategy - next auth - Email not found in the authentication token."
      );
    }

    const user = await this.userRepository.findByEmailWithProfile(token.email);
    if (!user) {
      throw new UnauthorizedException(
        "ApiAuthStrategy - next auth - User associated with the authentication token email not found."
      );
    }
    const organizationId = this.usersService.getUserMainOrgId(user) as number;
    request.organizationId = organizationId;

    return user;
  }

  async validateThirdPartyAccessToken(
    token: string,

View on GitHub (pinned to 176037d0af)

Solutions

  1. Use the platform OAuth flow (access token) or a static API key instead of the NextAuth session cookie for API calls.
  2. If you must use NextAuth, ensure the session was created with the same `next.authSecret` and includes the user's email claim.
  3. Log in to the web app first so the session cookie is fully populated before extracting it.
Defensive patterns

Strategy: validation

Validate before calling

const payload = decodeJwt(sessionJwt);
if (!payload?.email) throw new Error('Session token has no email claim; re-authenticate via the web app');

Type guard

function hasEmailClaim(p: unknown): p is { email: string } {
  return typeof p === 'object' && p !== null && typeof (p as any).email === 'string' && (p as any).email.length > 0;
}

Prevention

When it happens

Trigger: Sending a NextAuth session JWT (the cookie from app.cal.com) as a Bearer token to /v2 when that token's payload has no email (anonymous session, custom JWT, or a token from a different NextAuth instance whose secret differs).

Common situations: Grabbing the wrong cookie value; sending an unauthenticated NextAuth token; mismatch between the JWT signing secret used to mint the token and the API's next.authSecret env var (decoding succeeds but claims are partial).

Understand the failure class

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/a705bae46b57b56c. Report an issue: GitHub.