calcom/cal.diy · critical · ForbiddenException

EventTypeOwnershipGuard - No user associated with the…

Error message

EventTypeOwnershipGuard - No user associated with the request.

What it means

Thrown by EventTypeOwnershipGuard.canActivate when request.user is undefined. The guard reads `const user = request.user as ApiAuthGuardUser | undefined` and immediately checks `if (!user)`. A missing user means the guard ran without prior authentication being established on the request object, so it raises ForbiddenException (HTTP 403) rather than 401.

Solutions

  1. Ensure ApiAuthGuard runs before EventTypeOwnershipGuard on the route/controller (order matters in @UseGuards).
  2. Confirm the route requires authentication (not marked @Public or skipped) so the auth middleware attaches request.user.
  3. In tests, set request.user to a valid ApiAuthGuardUser before invoking the guard.

Example fix

// before
@UseGuards(EventTypeOwnershipGuard, ApiAuthGuard)

// after
@UseGuards(ApiAuthGuard, EventTypeOwnershipGuard)
Defensive patterns

Strategy: validation

Validate before calling

if (!request.user) {
  throw new UnauthorizedException('Authentication required.');
}
// then proceed to EventTypeOwnershipGuard

Type guard

const hasApiUser = (req: Request): req is Request & { user: ApiAuthGuardUser } =>
  !!req.user && typeof (req.user as any).id !== 'undefined';

Prevention

When it happens

Trigger: An event-type route decorated with @UseGuards(EventTypeOwnershipGuard) is hit without the ApiAuthGuard (or equivalent auth middleware) having populated request.user — e.g. guard ordering wrong, route accidentally public, or a test request with no auth setup.

Common situations: Guard listed before the auth guard in the @UseGuards array; a new route added without the auth guard; integration tests call the controller without mocking request.user; a middleware bug clears request.user.

Related errors


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

Appendix: source

Thrown at apps/api/v2/src/modules/event-types/guards/event-type-ownership.guard.ts:23

  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
  NotFoundException,
} from "@nestjs/common";
import { Request } from "express";

@Injectable()
export class EventTypeOwnershipGuard implements CanActivate {
  constructor(private readonly eventTypesService: EventTypesService_2024_06_14) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest<Request>();
    const user = request.user as ApiAuthGuardUser | undefined;
    const eventTypeIdParam = request.params?.eventTypeId;

    if (!user) {
      throw new ForbiddenException("EventTypeOwnershipGuard - No user associated with the request.");
    }

    if (!eventTypeIdParam) {
      throw new BadRequestException("Missing eventTypeId param.");
    }

    const eventTypeId = Number(eventTypeIdParam);
    if (!Number.isInteger(eventTypeId) || eventTypeId <= 0) {
      throw new BadRequestException("Invalid eventTypeId param.");
    }
    const eventType = await this.eventTypesService.getUserEventType(user.id, eventTypeId);
    if (!eventType) {
      // Mirrors EventTypesService behavior: NotFound when not owned or not present
      throw new NotFoundException(`Event type with id ${eventTypeId} not found`);
    }

    return true;
  }

View on GitHub (pinned to 176037d0af)