paperclipai/paperclip · error
Attachment exceeds the configured size limit
Error message
Attachment exceeds the configured size limit
What it means
Thrown in PhotonAdapter.publish when an attachment's byte size (Buffer length after normalizing Blob/ArrayBuffer data) exceeds MAX_ATTACHMENT_BYTES, the configured ceiling. The adapter checks locally before uploading so oversized payloads never hit the Photon API.
Solutions
- Shrink or re-encode the attachment (compress images, trim logs, lower bitrate on media) until it fits the limit
- Check bytes.length (or file.data.size for Blob) before calling publish and refuse the file earlier in your own code
- Raise MAX_ATTACHMENT_BYTES in configuration if the Photon server actually accepts larger payloads
- Link the artifact instead of attaching it (upload elsewhere and send a URL as text)
Example fix
// before
await adapter.publish(id, pubId, { text: 'report', files: [bigFile] }, opts);
// after
const bytes = bigFile.data instanceof Blob ? await bigFile.arrayBuffer() : bigFile.data;
if (bytes.byteLength > MAX_ATTACHMENT_BYTES) {
bigFile = await compressAttachment(bigFile);
}
await adapter.publish(id, pubId, { text: 'report', files: [bigFile] }, opts); Defensive patterns
Strategy: validation
Validate before calling
const MAX = MAX_ATTACHMENT_BYTES;
for (const f of message.files ?? []) {
const size = f.data instanceof Blob ? f.data.size : f.data.byteLength;
if (size > MAX) throw new Error(`Attachment ${f.filename} is ${size} bytes, limit ${MAX}`);
} Type guard
function withinLimit(file, max = MAX_ATTACHMENT_BYTES) {
const size = file.data instanceof Blob ? file.data.size : file.data.byteLength;
return size <= max;
} Try / catch
try {
await adapter.publish(id, pubId, msg, opts);
} catch (e) {
if (e.message === 'Attachment exceeds the configured size limit') {
return publishAsLink(id, pubId, msg, opts); // attach URL instead
}
throw e;
} Prevention
- Check attachment sizes at ingest time, before queueing a publication
- Compress images/media automatically when over the limit
- Keep MAX_ATTACHMENT_BYTES config in sync with iMessage's practical limits
- Prefer linking large artifacts over attaching them
When it happens
Trigger: publish() with message.files[i] whose data (Blob or ArrayBuffer) converts to a Buffer longer than MAX_ATTACHMENT_BYTES; checked in the per-file loop before sendPart is called for that file.
Common situations: Attaching large screenshots, logs, or generated PDFs; uploading video recordings (.mp4) from agent runs; MAX_ATTACHMENT_BYTES configured lower than the source data (e.g. iMessage's ~100MB practical ceiling vs a stricter instance config).
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
- HEIF decoded image exceeds the pixel limit
- A full lowercase source SHA is required.
- A reusable lease cannot be replaced and reacquired in the…
- A reusable lease handoff requires an execution workspace…
- A safe, unique --revision is required
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/2622765ae655045d.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/photon/adapter.ts:446
{
chatGuid: chat.guid,
text: parts[index],
replyTo: options.replyTo,
replaceMessageId: options.replaceMessageId,
},
undefined,
options,
);
messageIds.push(lastId);
}
for (let index = 0; index < files.length; index++) {
const file = files[index];
const bytes =
file.data instanceof Blob
? Buffer.from(await file.data.arrayBuffer())
: Buffer.from(file.data as ArrayBuffer);
if (bytes.length > MAX_ATTACHMENT_BYTES)
throw new Error("Attachment exceeds the configured size limit");
lastId = await this.sendPart(
publicationId,
`file-${index}`,
{
chatGuid: chat.guid,
filename: file.filename,
sha256: createHash("sha256").update(bytes).digest("hex"),
replyTo: options.replyTo,
},
{ ...file, data: bytes },
options,
);
messageIds.push(lastId);
}
if (!lastId) throw new Error("Photon publication is empty");
await this.endTyping(id);
return { id: lastId, messageIds };
}View on GitHub (pinned to 3f1d897a7c)