calcom/cal.diy · error · ConflictException
Webhook with this subscriber url already exists for this eve
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.
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)
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 eve
- Webhook with this subscriber url already exists for this oAu
- Webhook with this subscriber url already exists for this use
- 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.