{"record":{"id":"46aea4bfbc271f02","repo":"agalwood/Motrix","slug":"transient-failure","errorCode":"transient-failure","errorMessage":"manifest fetch failed: ${msg}","messagePattern":"manifest fetch failed: (.+?)","errorType":"error_code","errorClass":"BridgeReceiverError","httpStatus":null,"severity":"error","filePath":"src/core/bridge-receiver/pipelines/hls-dash-pipeline.ts","lineNumber":54,"sourceCode":"export class HlsDashPipeline {\n  constructor(private readonly deps: HlsDashPipelineDeps) {}\n\n  async dispatch(\n    adapted: AdaptedHls | AdaptedDash\n  ): Promise<{ taskId: string }> {\n    const { fetchManifest, coordinator } = this.deps\n    const headers = adapted.sanitizedHeaders\n    // ffmpeg needs an output extension or it can't pick a muxer (exit 234) —\n    // a manifest-derived finalName may lack one. Compute once for all branches.\n    const finalName = ensureMediaExtension(adapted.finalName, adapted.container)\n\n    // --- fetch primary manifest ---\n    let manifestText: string\n    try {\n      manifestText = await fetchManifest(adapted.manifestUrl, { headers })\n    } catch (e) {\n      const msg = e instanceof Error ? e.message : String(e)\n      throw new BridgeReceiverError(\n        'transient-failure',\n        `manifest fetch failed: ${msg}`\n      )\n    }\n\n    try {\n      if (adapted.kind === 'dash') {\n        // DASH\n        const { video, audio } = parseDash(manifestText, adapted.manifestUrl)\n        const job: MediaJob = {\n          taskId: adapted.taskId,\n          kind: 'dash',\n          video,\n          ...(audio !== undefined ? { audio } : {}),\n          headers,\n          saveDir: adapted.saveDir,\n          finalName,\n          sourceMeta: adapted.sourceMeta,","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/bridge-receiver/pipelines/hls-dash-pipeline.ts#L36-L72","documentation":"Thrown by HlsDashPipeline.dispatch when the primary manifest fetch (fetchManifest) rejects. The underlying fetch error message is wrapped into a BridgeReceiverError with code 'transient-failure', signaling to the extension that this is a retryable network-level failure, not a permanent rejection. This covers the initial GET of the HLS master/media playlist or DASH MPD.","triggerScenarios":"fetchManifest(adapted.manifestUrl, { headers }) rejects due to a network error, DNS failure, connection reset, HTTP 4xx/5xx, TLS error, or timeout. The manifestUrl is the primary playlist/MPD URL from the adapted selection.","commonSituations":"CDN outage or transient 503; expired signed URL (403); geo-blocked manifest; DNS resolution failure in a restrictive network; manifest URL became stale between extension detection and submit; proxy/firewall blocking the request.","solutions":["Retry the submit — 'transient-failure' is designed for retry; the underlying cause may resolve on its own","Check the embedded error message for the HTTP status (e.g. 403 → auth/cookie expiry, 404 → stale URL)","Verify network connectivity and that the manifestUrl is still reachable from a browser","For 403s, ensure cookies/headers are correctly forwarded — check that serialized headers include auth tokens like SESSDATA"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"async function isManifestReachable(url: string, headers?: Record<string, string>): Promise<boolean> {\n  try {\n    const res = await fetch(url, { headers, method: 'HEAD' })\n    return res.ok\n  } catch { return false }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await receiver.handleSubmit(params)\n} catch (e) {\n  if (e instanceof BridgeReceiverError && e.code === 'transient-failure' && e.message.startsWith('manifest fetch failed')) {\n    // Retry with backoff — transient by design\n    await sleep(2000)\n    await receiver.handleSubmit(params)\n  } else throw e\n}","preventionTips":["Treat 'transient-failure' as retryable in your error handler with exponential backoff","Check the embedded HTTP status in the message to distinguish auth expiry (403) from outages (503)"],"tags":["network","hls","dash","manifest","transient"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}