paperclipai/paperclip · error

Chat SDK webhook handler is unavailable for ${this.provider}

Error message

Chat SDK webhook handler is unavailable for ${this.provider}

What it means

Each Chat SDK provider must register a webhook handler under chat.webhooks[sdkAdapterKey]. When an inbound webhook arrives for a provider whose handler was never registered (chat.webhooks[this.sdkAdapterKey] is falsy), the runtime throws this error naming the provider.

Source

Thrown at server/src/services/chat-sdk-runtime.ts:2352

  async handleWebhook(
    request: Request,
    options?: WebhookOptions,
    responseDeadlineAt?: number,
    serviceReceivedAtMs?: number,
  ): Promise<Response> {
    this.assertNotRetired();
    // A body read, identity initialization or durable queue wait cannot mint
    // a fresh provider response window for an already received callback.
    const runtimeReceivedAtMs = Date.now();
    const receivedAtMs =
      typeof serviceReceivedAtMs === "number" &&
      Number.isSafeInteger(serviceReceivedAtMs) &&
      serviceReceivedAtMs > 0
        ? Math.min(serviceReceivedAtMs, runtimeReceivedAtMs)
        : runtimeReceivedAtMs;
    const handler = this.chat.webhooks[this.sdkAdapterKey];
    if (!handler) {
      throw new Error(
        `Chat SDK webhook handler is unavailable for ${this.provider}`,
      );
    }
    const providerUpdateId =
      this.provider === "telegram"
        ? await telegramWebhookUpdateId(request)
        : undefined;
    const attempt: WebhookIngressAttempt = {
      receivedAtMs,
      callbackError: undefined,
      callbackPromises: new Set(),
      ...(providerUpdateId !== undefined ? { providerUpdateId } : {}),
    };
    const sdkTasks: Promise<unknown>[] = [];
    const deadlineAt = Math.min(
      Date.now() + this.webhookIngressTimeoutMs,
      responseDeadlineAt ?? Number.POSITIVE_INFINITY,
    );

View on GitHub (pinned to 01ad858492)

Solutions

  1. Ensure chat.initialize() completes before webhook routes accept traffic.
  2. Confirm the adapter registers itself under the expected sdkAdapterKey in chat.webhooks.
  3. Check startup logs for adapter initialization failures that left the webhook map empty.
  4. Align the provider name in webhook route config with the registered SDK adapter key.

Example fix

// before
app.post("/webhooks/telegram", handler); // adapter never registered
// after
await chat.initialize();
if (!chat.webhooks[telegramSdkAdapterKey]) {
  throw new Error("telegram adapter failed to register its webhook handler");
}
app.post("/webhooks/telegram", handler);
Defensive patterns

Strategy: try-catch

Validate before calling

await chat.initialize();
const handler = chat.webhooks[sdkAdapterKey];
if (!handler) throw new Error(`no webhook handler registered for key ${sdkAdapterKey}`);

Type guard

null

Try / catch

try {
  await runtime.handleWebhook(request, runtimeReceivedAtMs);
} catch (err) {
  if (/webhook handler is unavailable/.test(String(err?.message))) {
    logger.error({ provider: runtime.provider }, "provider adapter not registered; check initialization and adapter key");
  }
  throw err;
}

Prevention

When it happens

Trigger: POSTing a webhook update to the endpoint for a provider whose adapter was not registered in chat.webhooks — e.g. sdkAdapterKey mismatch, adapter not initialized, or webhook route enabled for a provider the runtime doesn't support.

Common situations: Env/config enables a provider's webhook but the adapter failed to initialize earlier (swallowing an init error); SDK upgrade changed the adapter key; provider string and adapter key out of sync; starting webhook routes before chat.initialize() completes.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/a2e20f648250cf81. Report an issue: GitHub.