paperclipai/paperclip · error · GitHubAttachmentUnavailableError
github_attachment_invalid_response
github_attachment_invalid_response
Error message
github_attachment_invalid_response
What it means
After streaming, the service compares the received byte count against the Content-Length header at chat-github-attachments.ts:811-819 and throws GitHubAttachmentUnavailableError with code "github_attachment_invalid_response" on mismatch — but only when no Content-Encoding header is present, because Content-Length then describes compressed bytes, not the decoded size the reader observed. This detects truncated or tampered downloads.
Source
Thrown at server/src/services/chat-github-attachments.ts:817
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",
);
const body = Buffer.concat(chunks, size);
if (
!imageSignatureMatches(body, mimeType) ||
/^\s*(?:<!doctype\s+html|<html\b)/i.test(
body.subarray(0, 512).toString("utf8"),
)
)
throw new GitHubAttachmentUnavailableError(
"github_attachment_invalid_response",
);
const name = attachment.name?.startsWith("github-attachment-")
? `${attachment.name}${MIME_EXTENSIONS[mimeType] ?? ""}`
: attachment.name;
return {
type: mimeType.startsWith("image/")
? "image"View on GitHub (pinned to 01ad858492)
Solutions
- Retry the download — transient truncation often resolves on a fresh request
- Remove/fix intermediaries (proxies, compression middleware) that set inconsistent Content-Length/Content-Encoding pairs
- If compressing, ensure Content-Length is omitted or matches the compressed bytes with Content-Encoding set
- Validate the URL serves the asset directly without rewriting
Example fix
// before: test double with mismatched headers
new Response(buffer.slice(0, 10), { headers: { "content-length": String(buffer.length) } });
// after: consistent headers and body
new Response(buffer, { headers: { "content-length": String(buffer.length), "content-type": "image/png" } }); Defensive patterns
Strategy: retry
Validate before calling
const head = await fetch(url, { method: "HEAD" }); const declared = head.headers.get("content-length"); const enc = head.headers.get("content-encoding"); if (declared && !enc) expectedSize = Number(declared); // compare after download Type guard
null
Try / catch
for (let attempt = 0; attempt < 2; attempt++) { try { return await prepareGitHubPublicAttachment(attachment, signal); } catch (e) { if (e?.code === "github_attachment_invalid_response" && attempt === 0) continue; throw e; } } Prevention
- Fix intermediaries that set Content-Length inconsistent with Content-Encoding
- Prefer proxies that pass GitHub responses through unmodified
- Retry once on transient truncation before surfacing the error
- Return accurate Content-Length in test doubles
When it happens
Trigger: Response declares Content-Length N without Content-Encoding, and the decoded stream delivers size !== N (truncated transfer, connection reset mid-body, lying proxy).
Common situations: Flaky networks or proxies truncating bodies; misconfigured compression middleware that sets Content-Length of the uncompressed size while also gzipping; custom test doubles with inconsistent headers/body lengths; HTTP/2 flow-control early termination.
Related errors
- github_attachment_empty
- github_attachment_canonical_api_access_denied | github_attac
- github_attachment_canonical_api_too_large
- github_attachment_canonical_html_unavailable
- github_attachment_canonical_file_unsupported
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/41e25a67ad907089.
Report an issue: GitHub.