remotion-dev/remotion · error · Error
src must be a string when using `nodeReader`
Error message
src must be a string when using `nodeReader`
What it means
Thrown by nodeReadContent when the src passed to the Node.js filesystem reader is not a string. The Node reader uses fs.createReadStream and fs.existsSync, both of which require a filesystem path string. URL objects, Blobs, or File instances are not supported by nodeReader.
Source
Thrown at packages/media-parser/src/readers/from-node.ts:16
import {createReadStream, existsSync, promises, statSync} from 'fs';
import {dirname, join, relative, sep} from 'path';
import type {
CreateAdjacentFileSource,
MediaParserReaderInterface,
ReadContent,
ReadWholeAsText,
} from './reader';
export const nodeReadContent: ReadContent = async ({
src,
range,
controller,
}) => {
if (typeof src !== 'string') {
throw new Error('src must be a string when using `nodeReader`');
}
await Promise.resolve();
const ownController = new AbortController();
try {
if (!existsSync(src)) {
throw new Error(`File does not exist: ${src}`);
}
const stream = createReadStream(src, {
start: range === null ? 0 : typeof range === 'number' ? range : range[0],
end:
range === null
? Infinity
: typeof range === 'number'
? InfinityView on GitHub (pinned to 78fe4bb3fd)
Solutions
- Pass a filesystem path string to nodeReader, e.g. '/abs/path/media.mp4' or a relative path resolved from process.cwd().
- If you have a URL, convert it first: for file:// URLs use url.fileURLToPath(url); for http URLs switch to fetchReader.
- If you have a Blob/File in Node, write it to a temp file and pass the path, or use a reader that accepts streams.
Example fix
// before
await parseMedia({ src: new URL('file:///tmp/a.mp4'), fields: {...} }); // node reader
// after
import { fileURLToPath } from 'node:url';
await parseMedia({ src: fileURLToPath('file:///tmp/a.mp4'), fields: {...} }); Defensive patterns
Strategy: validation
Validate before calling
function assertNodePath(src: unknown): asserts src is string {
if (typeof src !== 'string') throw new TypeError('nodeReader requires a filesystem path string');
}
assertNodePath(src); Type guard
const isNodePath = (s: unknown): s is string => typeof s === 'string' && !s.startsWith('http'); Try / catch
try { await parseMedia({ src, srcType: 'node', fields }); } catch (e) { if (/src must be a string when using `nodeReader`/.test(String((e as Error).message))) { src = fileURLToPath(src); /* retry */ } else throw e; } Prevention
- Normalize URL/File inputs to path strings at the boundary of your Node code.
- Use fileURLToPath for file:// URLs before passing to nodeReader.
- Keep one helper that decides node vs fetch reader based on src type.
When it happens
Trigger: Calling parseMedia with srcType 'node' (or nodeReader explicitly) while passing a URL object, Blob, or File as src instead of a filesystem path string. This trips before any filesystem access is attempted.
Common situations: Sharing a src value between a browser (URL/File) and a Node SSR/render context without normalizing it. Receiving a file:// URL object from another API and passing it straight to the Node reader. Accidentally selecting nodeReader in an Electron/browser environment.
Related errors
- File does not exist: ${src}
- src must be a string or URL when using `fetchReader`
- Path is outside of the parent directory - not allowing readi
- `inputTypeFileReader` only supports `File` objects
- Not enough bytes left to parse EBML - this should not happen
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/bfa0d97806aa9db3.
Report an issue: GitHub.