paperclipai/paperclip · error

GitHub returned an unreadable webhook configuration. Reconne

Error message

GitHub returned an unreadable webhook configuration. Reconnect to confirm the callback settings.

What it means

Thrown by resyncGitHubAppWebhook when the response body from GitHub's webhook configuration GET cannot be read or parsed as a JSON object. After confirming status 200, the code streams the body with a bounded reader, JSON-parses it, and requires an object; any read error, truncation, or non-object payload (array, string, null) triggers this. Provider bodies are treated as untrusted, so no raw body is exposed.

Source

Thrown at server/src/services/chat-github-webhook-config.ts:765

    const chunks: Uint8Array[] = [];
    let size = 0;
    while (true) {
      const chunk = await reader.read();
      if (chunk.done) break;
      size += chunk.value.byteLength;
      if (size > MAX_CONFIG_RESPONSE_BYTES) {
        throw new Error("Oversized webhook configuration response");
      }
      chunks.push(chunk.value);
    }
    const parsed: unknown = JSON.parse(Buffer.concat(chunks).toString("utf8"));
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
      throw new Error("Invalid webhook configuration response");
    }
    config = parsed as Record<string, unknown>;
  } catch {
    await reader?.cancel().catch(() => undefined);
    throw new Error(
      "GitHub returned an unreadable webhook configuration. Reconnect to confirm the callback settings.",
    );
  } finally {
    reader?.releaseLock();
  }
  if (
    config.url !== input.webhookUrl ||
    config.content_type !== "json" ||
    (config.insecure_ssl !== "0" && config.insecure_ssl !== 0)
  ) {
    throw new Error(
      "GitHub did not confirm the expected secure Paperclip webhook. Reconnect to retry.",
    );
  }
}

View on GitHub (pinned to 01ad858492)

Solutions

  1. Retry the resync via reconnecting the GitHub connection; this is often transient.
  2. Verify no proxy sits between the server and api.github.com rewriting or truncating responses.
  3. Check GitHub status page for incidents affecting API response bodies.
  4. Confirm the webhook config page for the App manually and fix settings there if the API keeps failing.
Defensive patterns

Strategy: retry

Type guard

function isWebhookConfig(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try { await resyncGitHubAppWebhook(input); }
catch (e) {
  if (e.message.includes('unreadable webhook configuration')) {
    // likely transient body corruption; retry once, then reconnect
    await retryWithBackoff(() => resyncGitHubAppWebhook(input), 2);
  }
}

Prevention

When it happens

Trigger: GitHub returns 200 but the body stream fails mid-read; response is truncated by a proxy; body is valid JSON but an array/string/number instead of an object; Content-Encoding mismatch causing the reader to error.

Common situations: Intercepting proxies or API gateways rewriting responses; GitHub partial outage returning malformed bodies; misconfigured compression middleware in front of the server; HTML error page injected by a captive portal despite a 200 status.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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