musistudio/claude-code-router · error · Error
Remote media result has no URL.
Error message
Remote media result has no URL.
What it means
Thrown by MediaService's download executor when the media execution result has no remoteUrl to fetch. The downloader needs the provider's artifact URL; a result without one cannot be downloaded locally.
Solutions
- Check result.remoteUrl before calling download; skip or handle local results separately
- If the provider should have returned a URL, inspect the raw provider response — a schema/API change may require a library update
- For tests, construct results with a remoteUrl pointing at a fixture server
Example fix
// before
const out = await media.download(result, signal);
// after
if (!result.remoteUrl) {
throw new Error(`Cannot download job ${result.id}: no remote URL`);
}
const out = await media.download(result, signal); Defensive patterns
Strategy: type-guard
Type guard
const hasRemoteUrl = (r: MediaExecutionResult): r is MediaExecutionResult & { remoteUrl: string } =>
typeof r.remoteUrl === "string" && r.remoteUrl.length > 0; Prevention
- Guard remoteUrl before download; skip local-only results
- Update the library when providers change response schemas
When it happens
Trigger: Calling download(result, signal) on a MediaExecutionResult whose remoteUrl is missing/empty — e.g. a result synthesized locally, an upload-only flow, or a provider response that returned no URL field.
Common situations: Passing a local-generation result to the downloader; provider schema change dropping the URL field; a mock/stub result in tests; job retried after a partial provider response.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Media model is not configured by a provider
- Provider does not configure a media API base URL.
- Provider does not declare generation support.
- A media model must be selected.
- Account endpoint returned a non-object payload.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/9ac718c4a96c8929.
Report an issue: GitHub.
Appendix: source
Thrown at packages/core/src/media/executors.ts:100
await delay(2000, undefined, { signal });
continue;
}
const status = readString(payload, "status")?.toLowerCase();
if (status === "done" || status === "completed" || status === "succeeded") {
const url = readNestedString(payload, ["video", "url"]) ?? readString(payload, "url");
if (!url) throw mediaError("invalid_api_response", `${this.target.providerName} video API completed without an artifact URL.`, false);
return { fileName: `${requestId}.mp4`, remoteUrl: url, usage: readUsage(payload) };
}
if (status === "failed" || status === "expired" || status === "canceled" || status === "cancelled") {
const message = readNestedString(payload, ["error", "message"]) ?? readString(payload, "message") ?? `Video generation ${status}.`;
throw mediaError(`video_${status}`, message, status === "failed");
}
await delay(2000, undefined, { signal });
}
}
async download(result: MediaExecutionResult, signal: AbortSignal): Promise<MediaExecutionResult> {
if (!result.remoteUrl) throw new Error("Remote media result has no URL.");
let response: Response | undefined;
let lastError: unknown;
for (let attempt = 1; attempt <= 3; attempt += 1) {
try {
const candidate = await fetchMediaArtifact(result.remoteUrl, this.target.providerBaseUrl, signal);
if (candidate.ok || (candidate.status < 500 && candidate.status !== 408 && candidate.status !== 429)) {
response = candidate;
break;
}
lastError = mediaError("artifact_download_failed", `Failed to download generated artifact: HTTP ${candidate.status}.`, true);
await candidate.body?.cancel();
} catch (error) {
if (isExplicitlyNonRetryableError(error)) throw error;
lastError = error;
}
if (attempt < 3) await delay(attempt * 500, undefined, { signal });
}
if (!response) throw lastError ?? mediaError("artifact_download_failed", "Failed to download generated artifact.", true);View on GitHub (pinned to 99f24806c6)