{"record":{"id":"9ac718c4a96c8929","repo":"musistudio/claude-code-router","slug":"remote-media-result-has-no-url","errorCode":null,"errorMessage":"Remote media result has no URL.","messagePattern":"Remote media result has no URL\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/media/executors.ts","lineNumber":100,"sourceCode":"        await delay(2000, undefined, { signal });\n        continue;\n      }\n      const status = readString(payload, \"status\")?.toLowerCase();\n      if (status === \"done\" || status === \"completed\" || status === \"succeeded\") {\n        const url = readNestedString(payload, [\"video\", \"url\"]) ?? readString(payload, \"url\");\n        if (!url) throw mediaError(\"invalid_api_response\", `${this.target.providerName} video API completed without an artifact URL.`, false);\n        return { fileName: `${requestId}.mp4`, remoteUrl: url, usage: readUsage(payload) };\n      }\n      if (status === \"failed\" || status === \"expired\" || status === \"canceled\" || status === \"cancelled\") {\n        const message = readNestedString(payload, [\"error\", \"message\"]) ?? readString(payload, \"message\") ?? `Video generation ${status}.`;\n        throw mediaError(`video_${status}`, message, status === \"failed\");\n      }\n      await delay(2000, undefined, { signal });\n    }\n  }\n\n  async download(result: MediaExecutionResult, signal: AbortSignal): Promise<MediaExecutionResult> {\n    if (!result.remoteUrl) throw new Error(\"Remote media result has no URL.\");\n    let response: Response | undefined;\n    let lastError: unknown;\n    for (let attempt = 1; attempt <= 3; attempt += 1) {\n      try {\n        const candidate = await fetchMediaArtifact(result.remoteUrl, this.target.providerBaseUrl, signal);\n        if (candidate.ok || (candidate.status < 500 && candidate.status !== 408 && candidate.status !== 429)) {\n          response = candidate;\n          break;\n        }\n        lastError = mediaError(\"artifact_download_failed\", `Failed to download generated artifact: HTTP ${candidate.status}.`, true);\n        await candidate.body?.cancel();\n      } catch (error) {\n        if (isExplicitlyNonRetryableError(error)) throw error;\n        lastError = error;\n      }\n      if (attempt < 3) await delay(attempt * 500, undefined, { signal });\n    }\n    if (!response) throw lastError ?? mediaError(\"artifact_download_failed\", \"Failed to download generated artifact.\", true);","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/media/executors.ts#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst out = await media.download(result, signal);\n\n// after\nif (!result.remoteUrl) {\n  throw new Error(`Cannot download job ${result.id}: no remote URL`);\n}\nconst out = await media.download(result, signal);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const hasRemoteUrl = (r: MediaExecutionResult): r is MediaExecutionResult & { remoteUrl: string } =>\n  typeof r.remoteUrl === \"string\" && r.remoteUrl.length > 0;","tryCatchPattern":null,"preventionTips":["Guard remoteUrl before download; skip local-only results","Update the library when providers change response schemas"],"tags":["media","download","missing-url","provider"],"backgroundTag":"missing-required-field","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}