{"record":{"id":"309f83d542a7651a","repo":"paperclipai/paperclip","slug":"attachment-exceeds-the-configured-size-limit-attachments","errorCode":null,"errorMessage":"Attachment exceeds the configured size limit","messagePattern":"Attachment exceeds the configured size limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/photon/attachments.ts","lineNumber":102,"sourceCode":"  const attachment = source.content.attachments.find(\n    (candidate) => candidate.guid === locator.attachmentGuid,\n  );\n  if (\n    source.guid !== locator.messageGuid ||\n    !source.chatGuids.includes(locator.chatGuid) ||\n    !attachment ||\n    attachment.isSticker ||\n    attachment.isHidden\n  )\n    throw new Error(\n      \"Photon attachment does not belong to this message and chat\",\n    );\n  if (\n    !Number.isSafeInteger(attachment.totalBytes) ||\n    attachment.totalBytes < 0 ||\n    attachment.totalBytes > MAX_ATTACHMENT_BYTES\n  )\n    throw new Error(\"Attachment exceeds the configured size limit\");\n  const stream = client.attachments.downloadStream(locator.attachmentGuid);\n  let timedOut = false;\n  const timer = setTimeout(() => {\n    timedOut = true;\n    void stream.close();\n  }, 30_000);\n  timer.unref();\n  const chunks: Uint8Array[] = [];\n  let length = 0;\n  let header = false;\n  let companionInfo: CompanionInfo | undefined;\n  let companionUnavailable = false;\n  let companionStarted = false;\n  let companionLength = 0;\n  const companionChunks: Uint8Array[] = [];\n  try {\n    for await (const part of stream) {\n      if (part.type === \"header\") {","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/attachments.ts#L84-L120","documentation":"Before streaming, the message's attachment metadata (attachment.totalBytes) is validated: it must be a safe non-negative integer no larger than MAX_ATTACHMENT_BYTES. Otherwise this error is thrown (server/src/services/photon/attachments.ts:102). It guards against downloading absurdly large or corrupt-size attachments.","triggerScenarios":"attachment.totalBytes is undefined/NaN/not a safe integer, negative, or greater than MAX_ATTACHMENT_BYTES as configured in server/src/attachment-types.js.","commonSituations":"A user sends a multi-hundred-MB video exceeding the configured cap; Photon metadata is missing totalBytes for an older message format; misconfigured attachment-size limit lower than expected media sizes.","solutions":["Check the attachment's totalBytes against MAX_ATTACHMENT_BYTES before calling and skip attachments that are too large.","Raise MAX_ATTACHMENT_BYTES in server/src/attachment-types.js if the limit is unintentionally small.","Treat non-numeric/missing totalBytes as a metadata problem: re-sync message metadata from Photon before downloading.","Ask the sender to resend as a smaller/compressed attachment when the size genuinely exceeds the cap."],"exampleFix":"// before\nawait downloadPhotonAttachment(client, lineId, locator); // may throw for big files\n// after\nconst att = message.raw.content.attachments.find(a => a.guid === locator.attachmentGuid);\nif (att.totalBytes > MAX_ATTACHMENT_BYTES) return skipAttachment(att, \"too large\");\nawait downloadPhotonAttachment(client, lineId, locator);","handlingStrategy":"validation","validationCode":"import { MAX_ATTACHMENT_BYTES } from \"../attachment-types.js\";\nconst att = message.raw.content.attachments.find(a => a.guid === locator.attachmentGuid);\nif (!Number.isSafeInteger(att?.totalBytes) || att.totalBytes < 0 || att.totalBytes > MAX_ATTACHMENT_BYTES) {\n  throw new Error(`attachment too large or invalid size: ${att?.totalBytes}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await downloadPhotonAttachment(client, lineId, locator);\n} catch (e) {\n  if (e instanceof Error && e.message === \"Attachment exceeds the configured size limit\") {\n    // record and skip; do not retry\n  } else throw e;\n}","preventionTips":["Check attachment.totalBytes against MAX_ATTACHMENT_BYTES before every download","Keep the configured limit in sync with the largest media your users send","Treat invalid/missing totalBytes metadata as a skip-and-log case, not a retry"],"tags":["size-limit","validation","attachments"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}