musistudio/claude-code-router · error
The CCR artifact request failed.
Error message
The CCR artifact request failed.
What it means
loadCodexMediaArtifact fetches a media (image/video) artifact from the Codex CCR artifact endpoint, and this error means the fetch itself threw — network failure, DNS error, TLS problem, invalid redirect (redirect: 'error'), or the request was aborted via the AbortSignal. The catch block deliberately discards the underlying cause and rethrows this generic message.
Source
Thrown at packages/core/src/agents/codex/media-preview-bridge.ts:302
}
const keys = [...url.searchParams.keys()];
const token = url.searchParams.get("token") || "";
if (keys.length !== 1 || keys[0] !== "token" || !/^[A-Za-z0-9_-]{32}$/.test(token)) {
throw new Error("Artifact URL contains an invalid access token.");
}
return { artifactId, url };
}
async function loadCodexMediaArtifact(validated: ValidatedArtifactUrl, signal: AbortSignal): Promise<LoadedMediaArtifact> {
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;View on GitHub (pinned to 99f24806c6)
Solutions
- Verify the artifact host is reachable from the process (curl the validated URL with accept: image/*, video/*)
- Check whether the URL redirects — redirects are rejected by design; fetch the artifact through its canonical non-redirecting URL
- If an AbortSignal/timeout is being passed, confirm it isn't firing before the download completes
- Inspect the original fetch error by temporarily logging the caught value before the rethrow, since the cause is swallowed
- If the CCR session was restarted, re-request the artifact reference to get a fresh URL
Example fix
// before
try {
const media = await bridge.artifact(ref);
} catch (e) {
console.error(e.message); // "The CCR artifact request failed." — cause lost
}
// after (in media-preview-bridge.ts, keep the cause)
} catch (cause) {
throw new Error("The CCR artifact request failed.", { cause });
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight reachability check (best-effort) before requesting the artifact
async function artifactReachable(url: string, signal?: AbortSignal): Promise<boolean> {
try {
const res = await fetch(url, { method: 'HEAD', redirect: 'error', signal });
return res.ok;
} catch { return false; }
} Type guard
function isArtifactRequestFailure(e: unknown): boolean {
return e instanceof Error && e.message === 'The CCR artifact request failed.';
} Try / catch
try {
const media = await bridge.artifact(ref);
} catch (e) {
if (isArtifactRequestFailure(e)) {
await sleep(backoffMs);
return bridge.artifact(ref); // network blips are often transient
}
throw e;
} Prevention
- Keep CCR sessions alive so artifact URLs don't expire
- Ensure network/proxy access to the artifact host from the runtime
- Use a generous AbortSignal timeout relative to artifact size
When it happens
Trigger: Calling artifact() for a CCR media attachment when the artifact URL is unreachable, the endpoint responds with a 3xx redirect (redirect: 'error' makes any redirect throw), the AbortSignal fires before completion, or fetch rejects due to DNS/TLS/network errors.
Common situations: Running in a sandboxed/offline CI environment, a proxy or firewall blocking the artifact host, the artifact URL being invalidated by restarting/expiring the CCR session, or an aggressive timeout on the AbortSignal.
Related errors
- The CCR artifact endpoint attempted a redirect.
- The CCR artifact endpoint returned HTTP ${response.status}.
- Claude App profiles do not support agent arguments.
- HTTP + response.status + from CCR remote sync
- The CCR artifact endpoint returned a non-media content type.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/f280328e308e7703.
Report an issue: GitHub.