musistudio/claude-code-router · warning

The CCR media artifact exceeds the inline preview size limit

Error message

The CCR media artifact exceeds the inline preview size limit.

What it means

The Content-Length header on the artifact response is missing, non-numeric, non-positive, or exceeds the inline preview cap (codexMediaPreviewMaxImageBytes for images, codexMediaPreviewMaxVideoBytes for videos). This is a pre-flight size check so oversized media is rejected before streaming the body.

Source

Thrown at packages/core/src/agents/codex/media-preview-bridge.ts:312

  let response: Response;
  try {
    response = await fetch(validated.url, {
      headers: { accept: "image/*, video/*" },
      redirect: "error",
      signal
    });
  } catch {
    throw new Error("The CCR artifact request failed.");
  }
  if (!response.ok) throw new Error(`The CCR artifact endpoint returned HTTP ${response.status}.`);
  if (response.redirected) throw new Error("The CCR artifact endpoint attempted a redirect.");
  const declaredMimeType = (response.headers.get("content-type") || "").split(";", 1)[0].trim().toLowerCase();
  const declaredKind = mediaKind(declaredMimeType);
  if (!declaredKind) throw new Error("The CCR artifact endpoint returned a non-media content type.");
  const maxBytes = declaredKind === "video" ? codexMediaPreviewMaxVideoBytes : codexMediaPreviewMaxImageBytes;
  const declaredLength = Number(response.headers.get("content-length") || "0");
  if (declaredLength && (!Number.isSafeInteger(declaredLength) || declaredLength < 1 || declaredLength > maxBytes)) {
    throw new Error("The CCR media artifact exceeds the inline preview size limit.");
  }
  if (response.headers.get("content-encoding") && response.headers.get("content-encoding") !== "identity") {
    throw new Error("Compressed CCR media artifacts are not accepted for inline preview.");
  }
  if (!response.body) throw new Error("The CCR artifact response had no body.");
  const reader = response.body.getReader();
  const chunks: Buffer[] = [];
  let total = 0;
  while (true) {
    const part = await reader.read();
    if (part.done) break;
    if (!part.value?.byteLength) continue;
    total += part.value.byteLength;
    if (total > maxBytes) {
      await reader.cancel();
      throw new Error("The CCR media artifact exceeds the inline preview size limit.");
    }
    chunks.push(Buffer.from(part.value));

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Check the artifact's actual size (HEAD or Content-Length) against the limits before requesting an inline preview
  2. If the media is legitimately large, render it as a link/external reference instead of an inline preview
  3. If the header value is malformed from your server, fix the endpoint to send a valid numeric Content-Length or omit it (omission is tolerated — streaming check in error 57 still applies)

Example fix

// before
const media = await bridge.artifact(ref); // throws if > limit

// after
if (ref.size != null && ref.size > maxInlineBytes) {
  renderAsLink(ref.url);
} else {
  const media = await bridge.artifact(ref);
}
Defensive patterns

Strategy: validation

Validate before calling

async function withinPreviewLimit(url: string, maxBytes: number): Promise<boolean> {
  const res = await fetch(url, { method: 'HEAD' });
  const len = Number(res.headers.get('content-length') || '0');
  return !len || (len >= 1 && len <= maxBytes);
}

Type guard

function isSizeLimitRejection(e: unknown): boolean {
  return e instanceof Error && e.message.includes('exceeds the inline preview size limit');
}

Try / catch

try {
  const media = await bridge.artifact(ref);
} catch (e) {
  if (isSizeLimitRejection(e)) return renderAsLink(ref);
  throw e;
}

Prevention

When it happens

Trigger: Artifact Content-Length > maxBytes for its declared kind; Content-Length header of '0' is fine, but a malformed/negative/non-safe-integer value triggers the same rejection.

Common situations: Trying to inline a 4K screenshot or long screen recording that exceeds the preview budget; a server sending a wrong Content-Length (e.g. '*' or a negative number); proxy-rewritten headers producing invalid lengths.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/69c4e2c7cae72655. Report an issue: GitHub.