musistudio/claude-code-router · error
Artifact URL contains an invalid access token.
Error message
Artifact URL contains an invalid access token.
What it means
The final check in validateCodexMediaArtifactUrl: the URL must carry exactly one query parameter named token whose value matches ^[A-Za-z0-9_-]{32}$ (a 32-char base64url token). Extra params, a missing token, a differently-named param, or wrong length/charset all throw this.
Source
Thrown at packages/core/src/agents/codex/media-preview-bridge.ts:288
return url.startsWith("app://codex") || url.startsWith("app://chatgpt") || /\b(codex|chatgpt)\b/i.test(target.title || "");
}
function validateCodexMediaArtifactUrl(value: string, endpoint: string): ValidatedArtifactUrl {
const expected = new URL(endpoint);
const url = new URL(value);
if (url.protocol !== "http:" || url.origin !== expected.origin) throw new Error("Artifact origin is not the configured CCR gateway.");
if (url.username || url.password || url.hash) throw new Error("Artifact URL contains unsupported credentials or fragments.");
if (!url.pathname.startsWith(MEDIA_ARTIFACT_PATH_PREFIX)) throw new Error("Artifact URL does not use the CCR media artifact path.");
const encodedId = url.pathname.slice(MEDIA_ARTIFACT_PATH_PREFIX.length);
if (!encodedId || encodedId.includes("/")) throw new Error("Artifact URL contains an invalid identifier.");
const artifactId = decodeURIComponent(encodedId);
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(artifactId)) {
throw new Error("Artifact URL contains an invalid identifier.");
}
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();View on GitHub (pinned to 99f24806c6)
Solutions
- Ensure the gateway issues the token as exactly 32 base64url characters (no padding) in the sole token query param
- Strip any extra query parameters before validating / stop appending them upstream
- If the token scheme legitimately changed, align this package's regex or pin compatible versions
Example fix
// before
validateCodexMediaArtifactUrl("http://gw/media/artifact/<uuid>?token=abc&src=cli", endpoint);
// after
validateCodexMediaArtifactUrl("http://gw/media/artifact/<uuid>?token=AbCdEfGhIjKlMnOpQrStUvWxYz012345", endpoint); Defensive patterns
Strategy: validation
Validate before calling
const u = new URL(artifactUrl);
const keys = [...u.searchParams.keys()];
const token = u.searchParams.get('token') || '';
if (keys.length !== 1 || keys[0] !== 'token' || !/^[A-Za-z0-9_-]{32}$/.test(token)) {
throw new Error('rejecting artifact with bad token');
} Type guard
function hasValidArtifactToken(value: string): boolean {
try { const u = new URL(value); const k = [...u.searchParams.keys()]; const t = u.searchParams.get('token') || ''; return k.length === 1 && k[0] === 'token' && /^[A-Za-z0-9_-]{32}$/.test(t); } catch { return false; }
} Prevention
- Ensure tokens are 32-char base64url with no padding
- Don't append extra query params to artifact links
- Validate token shape before calling the artifact loader
When it happens
Trigger: Artifact URL with no ?token=, with additional query params (?token=...&foo=1), a token shorter/longer than 32 chars, or containing characters outside A-Za-z0-9_- (e.g. '+', '=' from standard base64).
Common situations: Token generation changed to standard base64 (with + and =) or a different length; querystring parsers/gateways appending extra params like utm_ or sig; tokens stripped or re-encoded by proxies.
Related errors
- ${label} cannot include credentials.
- Only http, https, and CCR plugin URLs can be opened.
- Only http and https QR login URLs can be opened.
- Only http and https URLs can be opened.
- Artifact origin is not the configured CCR gateway.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/17eb425804484918.
Report an issue: GitHub.