calcom/cal.diy · error · BadRequestException
User with id=${newUserId} is not a valid Round Robin host -
Error message
User with id=${newUserId} is not a valid Round Robin host - the user to which you reassign this booking must be one of the booking hosts. Fetch the booking using the GET /v2/bookings/{uid} endpoint and select id of one of the hosts. What it means
Thrown in reassignBookingToUser's catch block when roundRobinManualReassignment rejects with the literal message "invalid_round_robin_host". NestJS BadRequestException (HTTP 400). It means the newUserId is not one of the designated round-robin hosts for the booking - manual reassignment may only target an existing host. The message itself tells the caller to GET the booking and pick a host id.
Source
Thrown at apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts:1113
reassignedById: reassignedByUser.id,
emailsEnabled,
platformClientParams,
actionSource: "API_V2",
reassignedByUuid: reassignedByUser.uuid,
});
const reassigned = await this.bookingsRepository.getByUidWithUser(bookingUid);
if (!reassigned) {
throw new NotFoundException(
`Reassigned booking with uid=${bookingUid} was not found in the database`
);
}
return this.outputService.getOutputReassignedBooking(reassigned);
} catch (error) {
if (error instanceof Error) {
if (error.message === "invalid_round_robin_host") {
throw new BadRequestException(
`User with id=${newUserId} is not a valid Round Robin host - the user to which you reassign this booking must be one of the booking hosts. Fetch the booking using the GET /v2/bookings/{uid} endpoint and select id of one of the hosts.`
);
}
}
throw error;
}
}
async confirmBooking(bookingUid: string, requestUser: ApiAuthGuardUser) {
const booking = await this.bookingsRepository.getByUid(bookingUid);
if (!booking) {
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
}
const platformClientParams = booking.eventTypeId
? await this.platformBookingsService.getOAuthClientParams(booking.eventTypeId)
: undefined;
View on GitHub (pinned to 176037d0af)
Solutions
- GET /v2/bookings/{uid} and choose newUserId strictly from the returned hosts array.
- If you need a non-host user, first add them as a host on the event type, then reassign.
- Re-fetch hosts immediately before the call to avoid stale host lists.
- Validate the chosen id against the live host set client-side.
Example fix
// before
await apiClient.post(`/v2/bookings/${uid}/reassign-to-user`, { userId: someUserId });
// after
const booking = await apiClient.get(`/v2/bookings/${uid}`).then(r => r.data);
const validHost = (booking.hosts ?? []).find(h => h.id === someUserId);
if (!validHost) throw new Error(`${someUserId} is not a round-robin host of booking ${uid}`);
await apiClient.post(`/v2/bookings/${uid}/reassign-to-user`, { userId: validHost.id }); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the target user is one of the booking's round-robin hosts
const booking = await apiClient.get(`/v2/bookings/${uid}`).then(r => r.data);
const validHost = (booking.hosts ?? []).find(h => h.id === newUserId);
if (!validHost) {
throw new Error(`User ${newUserId} is not a round-robin host of booking ${uid}; pick from [${(booking.hosts ?? []).map(h => h.id).join(', ')}]`);
} Type guard
function isRoundRobinHost(userId: number, booking: { hosts?: Array<{ id: number }> }): boolean {
return (booking.hosts ?? []).some(h => h.id === userId);
} Try / catch
try {
await apiClient.post(`/v2/bookings/${uid}/reassign-to-user`, { userId: newUserId });
} catch (err) {
if (err.response?.status === 400 && /not a valid Round Robin host/i.test(err.response?.data?.message ?? '')) {
const hosts = await apiClient.get(`/v2/bookings/${uid}`).then(r => (r.data.hosts ?? []).map(h => h.id));
throw new InvalidHostError(`Pick one of: ${hosts.join(', ')}`);
}
throw err;
} Prevention
- Always derive newUserId from GET /v2/bookings/{uid}.hosts.
- If a non-host must receive the booking, add them as an event-type host first.
- Re-fetch the host list right before the call to avoid staleness.
When it happens
Trigger: POST reassign-to-user with a newUserId who is a valid user but is NOT in the booking's host set (e.g., a teammate who was never added to the event type, or a user removed from the round-robin pool).
Common situations: Assuming any org member can receive the booking; using the booking owner id when they are no longer an active host; host membership changed between fetching the user and the call.
Related errors
- Can't reassign the booking because no other host is availabl
- User with id=${newUserId} was not found in the database
- ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNe
- teamId is required for team events, please provide a valid t
- username is required for non-team events, please provide a v
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/741fd4a00de08749.
Report an issue: GitHub.