calcom/cal.diy · error · ConflictException
Webhook with this subscriber url already exists for this…
Error message
Webhook with this subscriber url already exists for this event type
What it means
EventTypeWebhooksService.createEventTypeWebhook queries getEventTypeWebhookByUrl(eventTypeId, subscriberUrl); if a row already exists with that URL for the same event type, it throws ConflictException (HTTP 409). The (eventTypeId, subscriberUrl) pair is treated as unique.
Solutions
- Before creating, call the paginated list endpoint and check whether the subscriberUrl is already registered for this event type.
- Use a unique subscriberUrl per webhook (e.g. append a unique path segment).
- Treat HTTP 409 as 'already exists' and continue idempotently instead of erroring.
- De-duplicate retry payloads by subscriberUrl.
Example fix
// before
await api.createEventTypeWebhook(eventTypeId, { subscriberUrl, ... });
// after
const existing = await api.listEventTypeWebhooks(eventTypeId);
if (existing.find(w => w.subscriberUrl === subscriberUrl)) return existing.find(w => w.subscriberUrl === subscriberUrl);
await api.createEventTypeWebhook(eventTypeId, { subscriberUrl, ... }); Defensive patterns
Strategy: validation
Validate before calling
async function createIfMissingEventType(api, eventTypeId, body) {
const list = await api.getEventTypeWebhooksPaginated(eventTypeId, 0, 1000);
if (list.find(w => w.subscriberUrl === body.subscriberUrl)) return;
return api.createEventTypeWebhook(eventTypeId, body);
} Type guard
const isDuplicateUrl = (list: { subscriberUrl: string }[], url: string): boolean =>
list.some(w => w.subscriberUrl === url); Try / catch
try { await api.createEventTypeWebhook(eventTypeId, body); }
catch (e) {
if (e.status === 409) { /* treat as already registered, continue */ }
else throw e;
} Prevention
- Make subscriber URLs unique per registration.
- Treat HTTP 409 as idempotent success in retry logic.
- Pre-list webhooks before creating to avoid duplicate-trigger retries.
When it happens
Trigger: POSTing a webhook with a subscriberUrl that already exists for the same eventTypeId. Replaying a successful request, retrying after a timeout, or two clients registering the same callback URL.
Common situations: Idempotency-unaware retry logic; multiple integrations pointing at the same callback endpoint; development where the same ngrok URL is reused across attempts.
Related errors
- Webhook with this subscriber url already exists for this…
- Webhook with this subscriber url already exists for this…
- Webhook with this subscriber url already exists for this…
- Google Meet is already connected for this team.
- Ooo entry already exists.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/7f90038d9d777896.
Report an issue: GitHub.
Appendix: source
Thrown at apps/api/v2/src/modules/webhooks/services/event-type-webhooks.service.ts:26
@Injectable()
export class EventTypeWebhooksService {
constructor(private readonly webhooksRepository: WebhooksRepository) {}
async createEventTypeWebhook(eventTypeId: number, body: PipedInputWebhookType) {
validateWebhookUrl(body.subscriberUrl);
if (body.eventTriggers.includes(WebhookTriggerEvents.DELEGATION_CREDENTIAL_ERROR)) {
throw new BadRequestException(
"DELEGATION_CREDENTIAL_ERROR trigger is only available for organization webhooks"
);
}
const existingWebhook = await this.webhooksRepository.getEventTypeWebhookByUrl(
eventTypeId,
body.subscriberUrl
);
if (existingWebhook) {
throw new ConflictException("Webhook with this subscriber url already exists for this event type");
}
return this.webhooksRepository.createEventTypeWebhook(eventTypeId, {
...body,
payloadTemplate: body.payloadTemplate ?? null,
secret: body.secret ?? null,
});
}
getEventTypeWebhooksPaginated(eventTypeId: number, skip: number, take: number) {
return this.webhooksRepository.getEventTypeWebhooksPaginated(eventTypeId, skip, take);
}
async deleteAllEventTypeWebhooks(eventTypeId: number): Promise<{ count: number }> {
return this.webhooksRepository.deleteAllEventTypeWebhooks(eventTypeId);
}
}
View on GitHub (pinned to 176037d0af)