calcom/cal.diy · error · NotFoundException
Updated link not found
Error message
Updated link not found
What it means
First of two 'Updated link not found' guards in PrivateLinksService.updatePrivateLink. After repo.update returns, the result is checked: if it is falsy OR its (loosely-cast) `.count` is 0, NotFoundException is thrown: no row matched the (eventTypeId, link) pair, so nothing was updated. This is HTTP 404 because the targeted resource doesn't exist.
Source
Thrown at apps/api/v2/src/platform/event-types-private-links/services/private-links.service.ts:80
return this.outputService.transformArrayToOutput(mapped);
} catch (error) {
if (error instanceof Error) {
throw new BadRequestException(error.message);
}
throw new BadRequestException("Failed to get private links");
}
}
async updatePrivateLink(eventTypeId: number, input: UpdatePrivateLinkInput): Promise<PrivateLinkOutput> {
try {
const transformedInput = this.inputService.transformUpdateInput(input);
const updatedResult = await this.repo.update(eventTypeId, {
link: transformedInput.linkId,
expiresAt: transformedInput.expiresAt ?? null,
maxUsageCount: transformedInput.maxUsageCount ?? null,
});
if (!updatedResult || (updatedResult as any).count === 0) {
throw new NotFoundException("Updated link not found");
}
const updated = await this.repo.findWithEventTypeDetails(transformedInput.linkId);
if (!updated) throw new NotFoundException("Updated link not found");
const mapped: PrivateLinkData = {
id: updated.link,
eventTypeId,
isExpired: isLinkExpired(updated as any),
bookingUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL || "https://cal.com"}/d/${updated.link}`,
expiresAt: updated.expiresAt ?? null,
maxUsageCount: updated.maxUsageCount ?? null,
usageCount: updated.usageCount ?? 0,
};
return this.outputService.transformToOutput(mapped);
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("not found")) {
throw new NotFoundException(error.message);
}View on GitHub (pinned to 176037d0af)
Solutions
- Verify the linkId exists for the given eventTypeId (GET /v2/event-types/{id}/private-links) before PATCHing.
- Refresh the client's link list if it may be stale.
- Treat a 404 on update as 'already gone' and refresh the list rather than retrying blindly.
Defensive patterns
Strategy: validation
Validate before calling
const links = await privateLinksService.getPrivateLinks(eventTypeId);
const exists = links.some(l => l.id === linkId);
if (!exists) {
return { status: 'not_found' }; // refresh the client's list instead of PATCHing
} Type guard
function isExistingLinkId(links: { id: string }[], linkId: string): boolean {
return links.some(l => l.id === linkId);
} Try / catch
try {
await privateLinksService.updatePrivateLink(eventTypeId, input);
} catch (e) {
if (e instanceof NotFoundException && e.message === 'Updated link not found') {
// refresh the link list; the linkId is stale or wrong
} else throw e;
} Prevention
- Refresh the link list before allowing an update.
- Match on the full linkId string (avoid truncation).
- Treat 404 on update as 'already gone' and refresh.
When it happens
Trigger: PATCH /v2/event-types/{id}/private-links/{linkId} where linkId doesn't exist under that eventTypeId; the link was already deleted; the linkId is correct but belongs to a different eventTypeId; a typo or truncated linkId in the request.
Common situations: Stale client showing a link that was since deleted; cross-event-type confusion; copy-paste of a linkId with a trailing character stripped; concurrent delete between GET and PATCH.
Related errors
- Team with id ${teamId} not found
- Event type with id ${eventTypeId} not found
- Payment with uid ${uid} not found
- Booking with uid ${uid} not found
- Event type with uid ${uid} not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/794389ee02464134.
Report an issue: GitHub.