remotion-dev/remotion · error · RangeError
writeAudioUntil() timestamps must be monotonically increasin
Error message
writeAudioUntil() timestamps must be monotonically increasing.
What it means
writeAudioUntil() enforces that each successive outputTimestamp is greater than or equal to the previously written timestamp. Media sinks cannot seek backwards while streaming, so a regressing timestamp raises a RangeError to protect the Opus encoder's monotonic timestamp contract.
Source
Thrown at packages/video-matting/src/prepare-audio.ts:242
if (primed || finished || canceled) {
return;
}
primed = true;
await writePacketsUntil({
outputTimestamp: 0,
writeAtLeastOne: true,
});
},
writeAudioUntil: async (outputTimestamp) => {
if (!Number.isFinite(outputTimestamp) || outputTimestamp < 0) {
throw new TypeError(
'outputTimestamp must be a finite, non-negative number.',
);
}
if (outputTimestamp < lastWriteTimestamp) {
throw new RangeError(
'writeAudioUntil() timestamps must be monotonically increasing.',
);
}
if (finished || canceled) {
return;
}
lastWriteTimestamp = outputTimestamp;
await writePacketsUntil({
outputTimestamp: Math.min(
outputTimestamp,
videoEndTimestamp - videoStartTimestamp,
),
writeAtLeastOne: false,
});
},
finishAudio: async () => {View on GitHub (pinned to b2f4e34732)
Solutions
- Ensure each call passes a timestamp >= the last one (monotonic, equal is allowed).
- Create a fresh pipeline with prepareAudio() when you need to restart from an earlier timestamp.
- Track lastTimestamp in the caller and skip or clamp calls that would go backwards.
Example fix
// before await audio.writeAudioUntil(currentFrame / fps); // currentFrame can decrease // after const t = Math.max(lastT, currentFrame / fps); await audio.writeAudioUntil(t); lastT = t;
Defensive patterns
Strategy: validation
Validate before calling
if (t < lastWritten) t = lastWritten; // or skip the call await audio.writeAudioUntil(t); lastWritten = t;
Type guard
null
Try / catch
try { await audio.writeAudioUntil(t); } catch (e) { if (e instanceof RangeError && e.message.includes('monotonically')) { lastWritten = 0; /* recreate pipeline */ } else throw e; } Prevention
- Track the last written timestamp in a variable and only move forward
- Recreate the pipeline on seek instead of rewinding
- Route all writes through a single serialized writer
When it happens
Trigger: Calling writeAudioUntil(5) after writeAudioUntil(10); restarting a render loop without re-calling prepareAudio; replaying a frame sequence with decreasing frame indices.
Common situations: Re-rendering a timeline segment in-place and rewinding the clock; off-by-one in a loop that passes the previous frame's timestamp; reusing a prepared audio pipeline across two renders.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ${label} encoding is not supported at ${size.width}×${size.h
- No supported configs
- Your browser does not support the WebCodecs ImageDecoder API
- Frame ${frame} is not finite
- Argument for frame must be an integer, but got ${frame}
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/fc0246d55e8ae157.
Report an issue: GitHub.