{"record":{"id":"1246808d94787ed3","repo":"remotion-dev/remotion","slug":"server-returned-status-res-status-while-fetchin","errorCode":null,"errorMessage":"Server returned status ${res.status} while fetching ${actualSrc}","messagePattern":"Server returned status (.+?) while fetching (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/video/OffthreadVideoForRendering.tsx","lineNumber":206,"sourceCode":"\t\t\ttry {\n\t\t\t\tconst res = await fetch(actualSrc, {\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tcache: 'no-store',\n\t\t\t\t});\n\t\t\t\tif (res.status !== 200) {\n\t\t\t\t\tif (res.status === 500) {\n\t\t\t\t\t\tconst json = await res.json();\n\t\t\t\t\t\tif (json.error) {\n\t\t\t\t\t\t\tconst cleanedUpErrorMessage = (json.error as string).replace(\n\t\t\t\t\t\t\t\t/^Error: /,\n\t\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tthrow new Error(cleanedUpErrorMessage);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Server returned status ${res.status} while fetching ${actualSrc}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst blob = await res.blob();\n\n\t\t\t\tconst url = URL.createObjectURL(blob);\n\t\t\t\tcleanup.push(() => URL.revokeObjectURL(url));\n\t\t\t\tsetImageSrc({\n\t\t\t\t\tsrc: url,\n\t\t\t\t\thandle: newHandle,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\t// If component is unmounted, we should not throw\n\t\t\t\tif ((err as Error).message.includes('aborted')) {\n\t\t\t\t\tcontinueRender(newHandle);\n\t\t\t\t\treturn;\n\t\t\t\t}","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/video/OffthreadVideoForRendering.tsx#L188-L224","documentation":"During a server render, `<OffthreadVideo>` fetches the extracted frame as a binary blob from the Remotion media-extraction endpoint. If the HTTP response status is anything other than 200 (and not a 500 with a parsed error body), this generic error is thrown with the status code and the resolved source URL.","triggerScenarios":"The frame-extraction server endpoint returns 4xx (e.g. asset not found, 404) or an unexpected 5xx, or the media URL is unreachable / misconfigured.","commonSituations":"Asset URL is wrong or not served by the render server, CORS or auth blocks the fetch, the source video is corrupt and the extractor fails partway, or running in an environment with restricted network egress.","solutions":["Verify the `src` URL resolves from the render environment (curl it from the same host).","Ensure the asset is reachable: serve it via `staticFile` or an absolute public URL.","Check the server logs for the matching request to see the underlying cause.","If intermittent, pass `onError` to `<OffthreadVideo>` to capture the failure rather than aborting the render."],"exampleFix":"// before\n<OffthreadVideo src=\"https://broken.example.com/missing.mp4\" />\n// after\n<OffthreadVideo src={staticFile('video.mp4')} />","handlingStrategy":"try-catch","validationCode":"// Validate reachability before render\nconst res = await fetch(src, {method: 'HEAD'});\nif (!res.ok) throw new Error(`Asset not reachable: ${res.status} for ${src}`);","typeGuard":"const isHttpOk = (status: number): boolean => status >= 200 && status < 300;","tryCatchPattern":"try {\n  await renderMedia(...);\n} catch (err) {\n  if (/Server returned status/.test((err as Error).message)) {\n    // surface asset URL / status to operator, retry or swap asset\n  }\n}","preventionTips":["Pre-fetch asset HEAD before rendering to confirm 200.","Host assets via `staticFile()` or a known-good CDN.","Pass `onError` to capture extraction failures without aborting the whole render."],"tags":["offthreadvideo","network","rendering","server","http"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}