{"record":{"id":"49a25f35fa22000c","repo":"musistudio/claude-code-router","slug":"the-ccr-artifact-response-was-empty","errorCode":null,"errorMessage":"The CCR artifact response was empty.","messagePattern":"The CCR artifact response was empty\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agents/codex/media-preview-bridge.ts","lineNumber":332,"sourceCode":"  if (response.headers.get(\"content-encoding\") && response.headers.get(\"content-encoding\") !== \"identity\") {\n    throw new Error(\"Compressed CCR media artifacts are not accepted for inline preview.\");\n  }\n  if (!response.body) throw new Error(\"The CCR artifact response had no body.\");\n  const reader = response.body.getReader();\n  const chunks: Buffer[] = [];\n  let total = 0;\n  while (true) {\n    const part = await reader.read();\n    if (part.done) break;\n    if (!part.value?.byteLength) continue;\n    total += part.value.byteLength;\n    if (total > maxBytes) {\n      await reader.cancel();\n      throw new Error(\"The CCR media artifact exceeds the inline preview size limit.\");\n    }\n    chunks.push(Buffer.from(part.value));\n  }\n  if (!total) throw new Error(\"The CCR artifact response was empty.\");\n  if (declaredLength && total !== declaredLength) throw new Error(\"The CCR artifact response length did not match its headers.\");\n  const bytes = Buffer.concat(chunks, total);\n  const detectedMimeType = detectMediaMimeType(bytes);\n  if (!detectedMimeType || mediaKind(detectedMimeType) !== declaredKind) {\n    throw new Error(\"The CCR artifact content did not match its declared media type.\");\n  }\n  return { bytes, mimeType: detectedMimeType };\n}\n\nfunction detectMediaMimeType(buffer: Buffer): string | undefined {\n  if (buffer.byteLength >= 8 && buffer.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) return \"image/png\";\n  if (buffer.byteLength >= 3 && buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) return \"image/jpeg\";\n  if (buffer.byteLength >= 12 && buffer.subarray(0, 4).toString(\"ascii\") === \"RIFF\" && buffer.subarray(8, 12).toString(\"ascii\") === \"WEBP\") return \"image/webp\";\n  if (buffer.byteLength >= 12 && buffer.subarray(4, 8).toString(\"ascii\") === \"ftyp\") {\n    const brand = buffer.subarray(8, 12).toString(\"ascii\");\n    if ([\"avif\", \"avis\", \"mif1\", \"msf1\"].includes(brand)) return \"image/avif\";\n    return \"video/mp4\";\n  }","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/agents/codex/media-preview-bridge.ts#L314-L350","documentation":"The artifact response body was consumed successfully but contained zero bytes (total === 0). An empty body cannot be a valid image or video, so it is rejected before MIME sniffing.","triggerScenarios":"Server returns 200 with correct Content-Type but an empty body (Content-Length: 0 or an immediately-ending stream); mocks returning empty Responses.","commonSituations":"Upstream bug writing an empty artifact; storage race where the artifact record exists but the object upload failed; test mocks with empty buffers.","solutions":["curl the artifact URL and confirm whether the body is genuinely empty server-side","If the artifact object is empty in storage, re-upload/re-generate it on the CCR side","In tests, ensure mocked responses include real media bytes"],"exampleFix":"// before\nglobal.fetch = async () => new Response(new Uint8Array(0), { headers: { 'content-type': 'image/png' } });\n\n// after\nglobal.fetch = async () => new Response(pngBytes, { headers: { 'content-type': 'image/png' } });","handlingStrategy":"try-catch","validationCode":"async function artifactHasBody(url: string): Promise<boolean> {\n  const res = await fetch(url, { method: 'HEAD' });\n  return Number(res.headers.get('content-length') || '0') !== 0;\n}","typeGuard":"function isEmptyArtifactRejection(e: unknown): boolean {\n  return e instanceof Error && e.message.includes('response was empty');\n}","tryCatchPattern":"try {\n  const media = await bridge.artifact(ref);\n} catch (e) {\n  if (isEmptyArtifactRejection(e)) return renderPlaceholder(ref);\n  throw e;\n}","preventionTips":["Verify artifact uploads completed before referencing them","Include real bytes in fetch mocks","Treat empty artifacts as corrupt data upstream, not as preview failures"],"tags":["empty-body","validation","media"],"backgroundTag":"empty-response-body","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}