{"record":{"id":"04acdb2e2d148a86","repo":"remotion-dev/remotion","slug":"the-offthreadvideo-tag-requires-a-string-for","errorCode":null,"errorMessage":"The `<OffthreadVideo>` tag requires a string for `src`, but got ${JSON.stringify(props.src)} instead.","messagePattern":"The `<OffthreadVideo>` tag requires a string for `src`, but got (.+?) instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/video/OffthreadVideo.tsx","lineNumber":46,"sourceCode":"\t\tname,\n\t\tpauseWhenBuffering,\n\t\t_remotionInternalStack,\n\t\tshowInTimeline,\n\t\t...otherProps\n\t} = props;\n\tconst environment = useRemotionEnvironment();\n\tconst shouldPauseWhenBuffering = resolveV5Default(pauseWhenBuffering);\n\n\tif (environment.isClientSideRendering) {\n\t\tthrow new Error(\n\t\t\t'<OffthreadVideo> is not supported in @remotion/web-renderer. Use <Video> from @remotion/media instead. See https://remotion.dev/docs/client-side-rendering/limitations',\n\t\t);\n\t}\n\n\tconst onDuration = useCallback(() => undefined, []);\n\n\tif (typeof props.src !== 'string') {\n\t\tthrow new TypeError(\n\t\t\t`The \\`<OffthreadVideo>\\` tag requires a string for \\`src\\`, but got ${JSON.stringify(\n\t\t\t\tprops.src,\n\t\t\t)} instead.`,\n\t\t);\n\t}\n\n\tvalidateMediaTrimProps({startFrom, endAt, trimBefore, trimAfter});\n\n\tconst {trimBeforeValue, trimAfterValue} = resolveTrimProps({\n\t\tstartFrom,\n\t\tendAt,\n\t\ttrimBefore,\n\t\ttrimAfter,\n\t});\n\n\tif (\n\t\ttypeof trimBeforeValue !== 'undefined' ||\n\t\ttypeof trimAfterValue !== 'undefined'","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/video/OffthreadVideo.tsx#L28-L64","documentation":"After the client-side-rendering check, `<OffthreadVideo>` enforces that `src` is a string. A non-string `src` (undefined, number, object) would break asset URL resolution and frame extraction downstream. The validator reports the JSON-stringified offending value.","triggerScenarios":"Passing `src={undefined}`, `src={someObject}`, or a dynamic prop that fails to resolve to a string into `<OffthreadVideo>`.","commonSituations":"Forgetting the `src` prop entirely, or passing a nested field of an asset object (e.g. `src={asset}` instead of `src={asset.url}`).","solutions":["Always pass a string URL to `src`, e.g. `src=\"https://.../video.mp4\"` or `src={staticFile('video.mp4')}`.","Use TypeScript: the prop type already requires `string`; tighten your types so the call site fails at compile time.","If loading src from data, narrow it first: `if (typeof src !== 'string') return null;`."],"exampleFix":"// before\n<OffthreadVideo src={asset} />\n// after\n<OffthreadVideo src={asset.url} />","handlingStrategy":"type-guard","validationCode":"if (typeof src !== 'string') {\n  throw new Error('OffthreadVideo src must be a string');\n}","typeGuard":"const isStringSrc = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":null,"preventionTips":["Type the wrapping component's props so `src: string` is required.","Always destructure asset URLs at the data boundary.","Use `staticFile()` for local assets to guarantee a string."],"tags":["offthreadvideo","src","validation","typescript"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}