paperclipai/paperclip · warning · GitHubAttachmentUnavailableError

github_attachment_too_large

github_attachment_too_large

Error message

github_attachment_too_large

What it means

During streamed download of a public GitHub attachment, the reader loop at chat-github-attachments.ts:799-802 accumulates bytes and throws GitHubAttachmentUnavailableError with code "github_attachment_too_large" as soon as the running size exceeds MAX_ATTACHMENT_BYTES. This mid-stream guard catches files whose size wasn't known up front (missing or lying Content-Length), aborting the download so oversized payloads never buffer in memory.

Source

Thrown at server/src/services/chat-github-attachments.ts:800

        (!/^\d+$/.test(declared) || Number(declared) > MAX_ATTACHMENT_BYTES)
      )
        return await rejectResponse("github_attachment_too_large");
      const reader = response.body.getReader();
      const chunks: Buffer[] = [];
      let size = 0;
      const cancel = () => {
        void reader.cancel().catch(() => undefined);
      };
      signal.addEventListener("abort", cancel, { once: true });
      try {
        for (;;) {
          signal.throwIfAborted();
          const next = await reader.read();
          signal.throwIfAborted();
          if (next.done) break;
          size += next.value.byteLength;
          if (size > MAX_ATTACHMENT_BYTES)
            throw new GitHubAttachmentUnavailableError(
              "github_attachment_too_large",
            );
          chunks.push(Buffer.from(next.value));
        }
      } finally {
        signal.removeEventListener("abort", cancel);
        await reader.cancel().catch(() => undefined);
      }
      if (!size)
        throw new GitHubAttachmentUnavailableError("github_attachment_empty");
      // Content-Length describes compressed bytes when Content-Encoding is present.
      if (
        declared &&
        !response.headers.get("content-encoding") &&
        size !== Number(declared)
      )
        throw new GitHubAttachmentUnavailableError(
          "github_attachment_invalid_response",

View on GitHub (pinned to 01ad858492)

Solutions

  1. Use a smaller attachment that fits within MAX_ATTACHMENT_BYTES
  2. Check the declared Content-Length before download and reject early with the same error
  3. Do not disable or raise MAX_ATTACHMENT_BYTES without reviewing memory limits
  4. Serve a pre-resized/compressed image (GitHub renders user-attachments images, but raw bytes still count)

Example fix

// before: attaching a 30MB video as a chat attachment
await prepareGitHubPublicAttachment({ url: bigVideoUrl });
// after: pre-check size and skip/notify
if (contentLength > MAX_ATTACHMENT_BYTES) return rejectAttachment("github_attachment_too_large");
Defensive patterns

Strategy: validation

Validate before calling

const head = await fetch(attachmentUrl, { method: "HEAD" }); const len = Number(head.headers.get("content-length") ?? 0); if (len > MAX_ATTACHMENT_BYTES) throw new Error("attachment exceeds size cap");

Type guard

null

Try / catch

try { return await prepareGitHubPublicAttachment(attachment, signal); } catch (e) { if (e?.code === "github_attachment_too_large") { return oversizedNotice(attachment); } throw e; }

Prevention

When it happens

Trigger: Downloading an attachment whose accumulated chunk bytes exceed MAX_ATTACHMENT_BYTES; also triggered earlier (line 780-784) when a numeric Content-Length header already exceeds the cap.

Common situations: Users attaching large videos or high-resolution images to GitHub issues; Content-Length absent due to chunked transfer so the stream guard is the only check; proxies stripping headers; misjudging the attachment cap when testing with large fixtures.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


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