paperclipai/paperclip · error

Photon companion metadata is missing

Error message

Photon companion metadata is missing

What it means

A companionChunk (Live Photo video part) may only arrive after a header established companionInfo. If a companionChunk arrives with header or companionInfo unset, this error is thrown (server/src/services/photon/attachments.ts:162) because the companion data cannot be validated or attributed.

Solutions

  1. Retry with a fresh download stream; ensure the previous stream was fully closed before retrying.
  2. Verify client/gateway version compatibility for Live Photo companion metadata framing.
  3. If the companion is optional, prefer a client/path that returns the primary image alone when companion metadata is absent.
  4. Report persistent cases to the Photon gateway team with messageGuid/attachmentGuid.
Defensive patterns

Strategy: retry

Try / catch

try {
  await downloadPhotonAttachment(client, lineId, locator);
} catch (e) {
  if (e instanceof Error && e.message === "Photon companion metadata is missing") {
    // retry once with a fresh stream; otherwise accept primary-only image
  } else throw e;
}

Prevention

When it happens

Trigger: Stream emits part.type === "companionChunk" before the header part, or the header part carried no companionInfo despite companion chunks following.

Common situations: Gateway dropping the header frame for a Live Photo; companionInfo omitted because the header part was consumed by a previous (retried) stream read; protocol mismatch between gateway and client library versions.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/73a6127d39348d81. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/photon/attachments.ts:162

            (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(
        "attachment_not_ready",
        "Photon attachment is still being prepared; retry download",
      );
    if (attachment.totalBytes > 0 && length !== attachment.totalBytes)
      throw new PhotonError(
        "attachment_not_ready",
        "Photon attachment transfer is incomplete",

View on GitHub (pinned to 3f1d897a7c)