remotion-dev/remotion · error · Error

Seeking infinite loop detected: Seeked to byte 0x${byte.toSt

Error message

Seeking infinite loop detected: Seeked to byte 0x${byte.toString(16)} ${lastSeek.numberOfTimes} times in a row in the last 2 seconds. Check your usage of .seek().

What it means

Thrown by the seek-state guard when the same byte offset is seeked to at least 10 times within a 2-second window. It detects pathological seek loops (typically caused by malformed media or parser bugs) that would otherwise spin forever, and aborts them with an actionable message pointing at .seek() usage.

Source

Thrown at packages/media-parser/src/state/seek-infinite-loop.ts:26

	let firstSeekTime: number | null = null;

	return {
		registerSeek: (byte: number) => {
			const now = Date.now();

			if (!lastSeek || lastSeek.byte !== byte) {
				lastSeek = {byte, numberOfTimes: 1};
				firstSeekTime = now;
				return;
			}

			lastSeek.numberOfTimes++;
			if (
				lastSeek.numberOfTimes >= 10 &&
				firstSeekTime &&
				now - firstSeekTime <= 2000
			) {
				throw new Error(
					`Seeking infinite loop detected: Seeked to byte 0x${byte.toString(16)} ${lastSeek.numberOfTimes} times in a row in the last 2 seconds. Check your usage of .seek().`,
				);
			}

			if (now - (firstSeekTime as number) > 2000) {
				lastSeek = {byte, numberOfTimes: 1};
				firstSeekTime = now;
			}
		},
		reset: () => {
			lastSeek = null;
			firstSeekTime = null;
		},
	};
};

export type SeekInfiniteLoop = ReturnType<
	typeof seekInfiniteLoopDetectionState

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Validate the media file with a tool like ffprobe before parsing; re-mux or re-download if it reports errors.
  2. If you control seek calls, ensure seeks advance based on parsed offsets rather than a fixed position.
  3. Catch the error to degrade gracefully and report the problematic media to the user.

Example fix

// before
controller._internals.seekTo(fixedByte); // called in a loop

// after
let advanced = computeNextOffset(lastParsedBox);
controller._internals.seekTo(advanced);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate with ffprobe (Node) before parseMedia
import { execSync } from 'node:child_process';
function isValidMedia(p: string): boolean { try { execSync(`ffprobe -v error "${p}"`, { stdio: 'ignore' }); return true; } catch { return false; } }

Try / catch

try { await parseMedia({ src, fields }); } catch (e) { if (/Seeking infinite loop detected/.test(String((e as Error).message))) { /* reject corrupt media, re-mux, or skip */ } else throw e; }

Prevention

When it happens

Trigger: A container whose structure causes the parser to repeatedly seek to the identical offset (circular box references, corrupt offset tables, a malformed index). Also triggered by custom parser extensions that misuse the seek API in a tight loop.

Common situations: Parsing a corrupt or truncated mp4/mov where stco/stsz tables point back to the same location. Hand-crafted test media with cyclic offsets. A controller/seek hook that always re-seeks to the same byte after each read.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/601fdb7035fe9588. Report an issue: GitHub.