paperclipai/paperclip · error
Photon attachment header is missing
Error message
Photon attachment header is missing
What it means
Primary data chunks must only arrive after a header part that establishes metadata. If a primaryChunk arrives while header is still false, the stream had no header first, and this error is thrown (server/src/services/photon/attachments.ts:155).
Solutions
- Retry the download with a fresh stream; transient truncation is usually recovered by re-requesting.
- Verify the @photon-ai/advanced-imessage client and gateway are version-compatible (header frame support).
- Confirm the attachment still exists and is downloadable via a fresh client.messages.get before streaming.
- If persistent, treat the attachment as unavailable and surface a recoverable failure instead of retrying endlessly.
Defensive patterns
Strategy: retry
Try / catch
try {
await downloadPhotonAttachment(client, lineId, locator);
} catch (e) {
if (e instanceof Error && e.message === "Photon attachment header is missing") {
// fresh-stream retry with small backoff; escalate if persistent
} else throw e;
} Prevention
- Retry with a fresh stream; header-less streams are usually transient truncations
- Verify gateway/client protocol compatibility after upgrades
- Confirm the attachment still exists via messages.get before streaming
When it happens
Trigger: The download stream yields part.type === "primaryChunk" before any part.type === "header" part.
Common situations: Gateway emitting truncated streams missing the header frame; protocol/version mismatch between client library and gateway; stream resumed mid-transfer where the header was dropped.
Related errors
- CreateOS process exit status is missing.
- CreateOS process output has a sequence gap.
- CreateOS process output is invalid.
- CreateOS process sequence is invalid.
- CreateOS returned an invalid process frame.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/20a5f9c6e17ea225.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/photon/attachments.ts:155
part.info.totalBytes > MAX_ATTACHMENT_BYTES
)
throw new Error("Photon attachment metadata changed");
header = true;
companionInfo = part.companionInfo;
companionUnavailable = Boolean(
companionInfo &&
(companionInfo.kind !== "live-photo-video" ||
!["video/quicktime", "video/mp4"].includes(
companionInfo.mimeType,
) ||
!Number.isSafeInteger(companionInfo.totalBytes) ||
companionInfo.totalBytes <= 0 ||
companionInfo.totalBytes > MAX_ATTACHMENT_BYTES),
);
} else if (part.type === "primaryChunk") {
if (companionStarted)
throw new Error("Photon attachment chunks arrived out of order");
if (!header) throw new Error("Photon attachment header is missing");
length += part.data.length;
if (length > MAX_ATTACHMENT_BYTES)
throw new Error("Attachment exceeds the configured size limit");
chunks.push(part.data);
} else if (part.type === "companionChunk") {
if (!header || !companionInfo)
throw new Error("Photon companion metadata is missing");
companionStarted = true;
companionLength += part.data.length;
if (companionUnavailable || companionLength > MAX_ATTACHMENT_BYTES) {
companionUnavailable = true;
break;
}
companionChunks.push(part.data);
}
}
if (timedOut || !header || !length)
throw new PhotonError(View on GitHub (pinned to 3f1d897a7c)