calcom/cal.diy · critical · BadRequestException
Failed to delete private link
Error message
Failed to delete private link
What it means
Fallback BadRequestException thrown by PrivateLinksService.deletePrivateLink when the caught value is not an Error instance. This defensive branch covers non-Error throws (strings, plain objects) from anywhere in the delete pipeline. The generic message hides the original cause, making it a debugging dead-end without instrumentation.
Source
Thrown at apps/api/v2/src/platform/event-types-private-links/services/private-links.service.ts:118
}
throw new BadRequestException("Failed to update private link");
}
}
async deletePrivateLink(eventTypeId: number, linkId: string): Promise<void> {
try {
const { count } = await this.repo.delete(eventTypeId, linkId);
if (count === 0) {
throw new NotFoundException("Deleted link not found");
}
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("not found")) {
throw new NotFoundException(error.message);
}
throw new BadRequestException(error.message);
}
throw new BadRequestException("Failed to delete private link");
}
}
}
View on GitHub (pinned to 176037d0af)
Solutions
- Search the codebase for `throw` of non-Error values and convert them to `throw new Error(...)`.
- Add structured logging in the catch block to capture the raw value and its type before the fallback fires.
- Wrap third-party calls so they always reject with Error instances.
- Consider this a defect to file against the service: a 400 with 'Failed to delete private link' is not actionable for a client.
Example fix
// before (downstream)
if (!conn) throw 'no db connection';
// after
if (!conn) throw new Error('no db connection'); Defensive patterns
Strategy: try-catch
Try / catch
try {
await api.delete(url);
} catch (e) {
if (e.response?.status === 400 && e.response?.data?.message === 'Failed to delete private link') {
// opaque server defect; retry once then escalate
} else throw e;
} Prevention
- Report to the server team — this fallback hides the real cause.
- Ensure your test doubles (mocks) reject with Error instances, not strings.
- Pin dependency versions to avoid transitive regressions in throw shapes.
When it happens
Trigger: A downstream method (repo.delete or Prisma internals) throwing a non-Error primitive; a Promise rejection with a raw value; an older dependency that throws strings; an internal assertion that rejects with a plain object.
Common situations: Custom repository code that does `throw 'delete failed'`; a mocked test double that rejects with a string; a transitive dependency regression after `yarn upgrade`. Because the message is generic, users cannot tell whether the link existed.
Related errors
- Failed to update private link
- Could not find public event.
- 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/b1a883d20e97d8f8.
Report an issue: GitHub.