{"record":{"id":"0b3190c1c0a9c6a8","repo":"remotion-dev/remotion","slug":"the-browser-threw-an-error","errorCode":null,"errorMessage":"The browser threw an error","messagePattern":"The browser threw an error","errorType":"exception","errorClass":"MediaPlaybackError","httpStatus":null,"severity":"error","filePath":"packages/core/src/video/VideoForRendering.tsx","lineNumber":239,"sourceCode":"\n\t\tcurrent.addEventListener('ended', endedHandler, {once: true});\n\n\t\tconst errorHandler = () => {\n\t\t\tif (current?.error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('Error occurred in video', current?.error);\n\n\t\t\t\t// If user is handling the error, we don't cause an unhandled exception\n\t\t\t\tif (onError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthrow new MediaPlaybackError({\n\t\t\t\t\tmessage: `The browser threw an error while playing the video ${props.src}: Code ${current.error.code} - ${current?.error?.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`,\n\t\t\t\t\tsrc: props.src as string,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthrow new MediaPlaybackError({\n\t\t\t\t\tmessage: 'The browser threw an error',\n\t\t\t\t\tsrc: props.src as string,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tcurrent.addEventListener('error', errorHandler, {once: true});\n\n\t\t// If video skips to another frame or unmounts, we clear the created handle\n\t\treturn () => {\n\t\t\tseek.cancel();\n\t\t\tcurrent.removeEventListener('ended', endedHandler);\n\t\t\tcurrent.removeEventListener('error', errorHandler);\n\t\t\tcontinueRender(handle);\n\t\t};\n\t}, [\n\t\tvolumePropsFrame,\n\t\tprops.src,","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/video/VideoForRendering.tsx#L221-L257","documentation":"Thrown by VideoForRendering's HTMLMediaElement 'error' event listener when the browser fires an error event on a <video> during server-side rendering but the element's `.error` property is null/undefined (so no detailed code or message is available). It is the fallback branch of the errorHandler: when `current?.error` is falsy, Remotion cannot report a specific browser error code, so it raises a generic MediaPlaybackError. If an `onError` prop is supplied, the throw is skipped so the user can handle it.","triggerScenarios":"The 'error' event fires on the video element during rendering AND `current.error` is null/undefined at the moment the handler runs. This happens when the media resource fails to load for a reason the browser does not attach an error object to (e.g. network abort, context loss, the element being torn down mid-seek), and no `onError` prop was passed to the <Video>/<VideoForRendering> component.","commonSituations":"Rendering a composition whose video src 404s or is intermittently unreachable; the media URL changes while a render is in flight; CORS/security header rejection that surfaces as an error event without a populated HTMLMediaError; flaky CDN during Lambda rendering where the request is aborted before the browser populates `.error`.","solutions":["Pass an `onError` prop to the <Video> component so Remotion does not throw and you can log/recover instead.","Verify the video `src` is reachable from the render environment (HTTP 200, correct CORS headers) before rendering.","Host the asset on the same origin or a CDN with `Access-Control-Allow-Origin` set, and use a server-rendering-friendly format (MP4/H.264 with faststart).","If the src is dynamic, ensure it resolves to a stable, fully loaded URL before the frame that plays it (preload with `staticFile()` or `usePreload`)."],"exampleFix":"// before\n<Video src={maybeFlakyUrl} />\n\n// after\n<Video\n  src={verifiedUrl}\n  onError={(e) => {\n    console.error('video error', e);\n  }}\n/>","handlingStrategy":"try-catch","validationCode":"import {getRemotionEnvironment} from 'remotion';\n\n// before rendering, confirm the URL is reachable\nconst ok = await fetch(src, {method: 'HEAD'}).then((r) => r.ok).catch(() => false);\nif (!ok) throw new Error(`Video src not reachable: ${src}`);","typeGuard":"const isReachableUrl = (u: string): boolean => {\n  try { return Boolean(new URL(u, window.location.origin)); } catch { return false; }\n};","tryCatchPattern":"<Video\n  src={src}\n  onError={(e) => {\n    // Remotion will NOT throw when onError is provided\n    console.error('video playback error', e, currentError);\n  }}\n/>","preventionTips":["Always pass an `onError` prop to <Video> so a browser error does not crash the render.","Preload media with staticFile()/usePreload so it is fully loaded before the playing frame.","Serve video from a CORS-enabled, range-supporting host."],"tags":["video","media-playback","rendering","browser","network"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}