calcom/cal.diy · error · NotFoundException
User with username ${input.username} not found
Error message
User with username ${input.username} not found What it means
A NestJS NotFoundException (HTTP 404) thrown by SlotsInputService_2024_09_04.getEventType when the request resolves an event type by username + event-type slug. The usersRepository.findByUsername(input.username) lookup returned null, so no user matches the supplied username. The error echoes the offending username so you can identify the bad reference.
Source
Thrown at apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-input.service.ts:102
const baseTransformation = await this.transformGetSlotsQuery(baseQuery);
return {
...baseTransformation,
routedTeamMemberIds: routedTeamMemberIds || null,
skipContactOwner: skipContactOwner || false,
teamMemberEmail: teamMemberEmail || null,
};
}
private async getEventType(input: GetSlotsInput_2024_09_04) {
if (input.type === ById_2024_09_04_type) {
return this.eventTypeRepository.getEventTypeById(input.eventTypeId);
}
if (input.type === ByUsernameAndEventTypeSlug_2024_09_04_type) {
const user = await this.getEventTypeUser(input);
if (!user) {
throw new NotFoundException(`User with username ${input.username} not found`);
}
return this.eventTypeRepository.getUserEventTypeBySlug(user.id, input.eventTypeSlug);
}
if (input.type === ByTeamSlugAndEventTypeSlug_2024_09_04_type) {
const team = await this.getEventTypeTeam(input);
if (!team) {
throw new NotFoundException(`Team with slug ${input.teamSlug} not found`);
}
return this.teamsEventTypesRepository.getEventTypeByTeamIdAndSlug(team.id, input.eventTypeSlug);
}
return input.duration ? { ...dynamicEvent, length: input.duration } : dynamicEvent;
}
private async getEventTypeUser(input: ByUsernameAndEventTypeSlug_2024_09_04) {
return await this.usersRepository.findByUsername(input.username);
}View on GitHub (pinned to 176037d0af)
Solutions
- Verify the username exists in the Cal.com app under /users or via the users API before calling slots.
- Confirm you are passing the `username` field (not email, not display name) and that it matches the user's profile slug exactly (case-sensitive).
- If the user belongs to an organization, pass the correct organizationSlug so the lookup hits the right tenant.
- Catch HTTP 404 in the client and surface a 'user not found' message to the end user with a prompt to re-check the link.
Example fix
// before
const res = await fetch(`/v2/slots?username=${email}&eventTypeSlug=30min`);
// after — use the actual username slug and validate first
const user = await calApi.getUserByUsername(username);
if (!user) throw new ClientError(`Unknown username: ${username}`);
const res = await fetch(`/v2/slots?username=${encodeURIComponent(user.username)}&eventTypeSlug=30min`); Defensive patterns
Strategy: validation
Validate before calling
import { DateTime } from 'luxon';
function assertUsernameResolvable(username: unknown): string {
if (typeof username !== 'string' || username.trim() === '') {
throw new TypeError('username must be a non-empty string');
}
// usernames are slugs — reject emails / display names early
if (/@\s|\s/.test(username)) {
throw new TypeError('Pass the username slug, not an email or display name');
}
return username.trim();
}
// Optional: confirm via GET /v2/users or the app before slots
const username = assertUsernameResolvable(input.username);
const user = await cal.users.getByUsername(username);
if (!user) throw new ClientError(`User '${username}' not found`); Type guard
function isByUsernameAndSlug(value: unknown): value is { username: string; eventTypeSlug: string } {
return typeof value === 'object' && value !== null
&& typeof (value as any).username === 'string'
&& typeof (value as any).eventTypeSlug === 'string';
} Try / catch
try {
await cal.slots.list({ type: 'usernameAndEventTypeSlug', username, eventTypeSlug, start, end });
} catch (e) {
if (e instanceof HttpError && e.statusCode === 404) {
// user does not exist — re-prompt, don't retry blindly
throw new UserFacingError('Booking link is invalid — user not found');
}
throw e;
} Prevention
- Resolve and cache the username from the user API rather than accepting free text.
- Pass organizationSlug when the user belongs to an org.
- URL-encode the username in query strings.
- Treat 404 as terminal for that link — do not auto-retry the same username.
When it happens
Trigger: Calling GET /v2/slots/2024-09-04 with type === "usernameAndEventTypeSlug" where the `username` field does not match any user record (typo, deleted user, unverified account, wrong org scope, or username moved to an organization subdomain).
Common situations: Hardcoding a username in an integration that was later renamed or deleted; passing the user's email instead of their username; querying before the user finished sign-up; username lives under an org slug that was not supplied via organizationSlug.
Related errors
- Team with slug ${input.teamSlug} not found
- Event Type with ID=${input.eventTypeId} not found
- Event Type not found
- Event Type not found
- Invalid start date
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/ec7cf78c08233aeb.
Report an issue: GitHub.