remotion-dev/remotion · error · Error
`reader` should not be provided to `${apiName}`. If you want
Error message
`reader` should not be provided to `${apiName}`. If you want to use it in the browser, use parseMediaOnWorker(). If you also want to read files from the file system, use parseMediaOnServerWorker(). What it means
parseMediaOnWorkerImplementation destructures {controller, reader, ...params} and immediately rejects if reader is truthy. The worker entry serializes options via postMessage, and a reader (with native handles / FS access) cannot cross the worker boundary. Browser workers use fetchReader implicitly; server FS reading needs the dedicated server worker.
Source
Thrown at packages/media-parser/src/parse-media-on-worker-entry.ts:114
postOnVideoTrack: Boolean(onVideoTrack),
// URL cannot be serialized, so we convert it to a string
src: src instanceof URL ? src.toString() : src,
};
};
const post = (worker: Worker, payload: WorkerRequestPayload) => {
worker.postMessage(payload);
};
export const parseMediaOnWorkerImplementation = async <
F extends Options<ParseMediaFields>,
>(
{controller, reader, ...params}: ParseMediaOptions<F>,
worker: Worker,
apiName: string,
) => {
if (reader) {
throw new Error(
`\`reader\` should not be provided to \`${apiName}\`. If you want to use it in the browser, use parseMediaOnWorker(). If you also want to read files from the file system, use parseMediaOnServerWorker().`,
);
}
post(worker, convertToWorkerPayload(params));
let workerTerminated = false;
const {promise, resolve, reject} =
withResolvers<ParseMediaResult<Options<ParseMediaFields>>>();
const onAbort = () => {
post(worker, {type: 'request-abort'});
};
const onResume = () => {
post(worker, {type: 'request-resume'});
};View on GitHub (pinned to 78fe4bb3fd)
Solutions
- For browser worker parsing, drop the reader option (fetchReader is used automatically): call parseMediaOnWorker without reader.
- For FS-backed parsing in a worker, use parseMediaOnServerWorker() WITHOUT passing reader — it uses nodeReader internally.
- For FS-backed parsing on the main thread, call parseMedia({reader: nodeReader, ...}).
- Check that you are importing the right function for your environment.
Example fix
// before (wrong)
import {nodeReader} from '@remotion/media-parser/node-reader';
await parseMediaOnServerWorker({src, reader: nodeReader, fields: {}});
// after (right): server worker wires nodeReader itself
await parseMediaOnServerWorker({src, fields: {}});
// or, main thread:
await parseMedia({src, reader: nodeReader, fields: {}}); Defensive patterns
Strategy: validation
Validate before calling
// Never pass reader to worker variants; choose the right entry point
function pickParseFn({needsFs, inWorker}: {needsFs: boolean; inWorker: boolean}) {
if (needsFs) return 'parseMediaOnServerWorker'; // uses nodeReader internally
if (inWorker) return 'parseMediaOnWorker';
return 'parseMedia';
} Type guard
import type {ParseMediaOptions} from '@remotion/media-parser';
const optsHaveReader = (o: ParseMediaOptions<any>): boolean => Boolean((o as any).reader); Try / catch
try {
await parseMediaOnServerWorker({src, fields: {}});
} catch (e) {
if (e instanceof Error && e.message.includes('`reader` should not be provided')) {
// caller passed reader by mistake; strip it and retry
throw new Error('Do not pass reader to worker variants');
}
throw e;
} Prevention
- Drop the reader option when calling parseMediaOnWorker / parseMediaOnServerWorker.
- Use parseMedia({reader: nodeReader}) on the main thread for FS reads.
- Remember server worker wires nodeReader internally.
- Document which entry point each environment should use.
When it happens
Trigger: Passing `reader: nodeReader` (or any custom reader) to parseMediaOnWorker or parseMediaOnServerWorker. The API expects readers only on the main-thread parseMedia / parseMediaOnServer.
Common situations: Wanting FS access inside a worker and assuming reader should be passed through; migrating from parseMedia to a worker variant without dropping the reader option; copy-paste from a Node parseMedia call.
Related errors
- Not enough bytes left to parse EBML - this should not happen
- has no bytes
- No "src" provided
- onError was used but did not return an "action" field. See d
- src must be a string when using `fetchReader`
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/2c61f4443922e51e.
Report an issue: GitHub.