remotion-dev/remotion · error · Error

Could not find offset for byte offset ${offset}

Error message

Could not find offset for byte offset ${offset}

What it means

Thrown at get-sample-from-block.ts:154 when `webmState.getTimestampOffsetForByteOffset(offset)` returns undefined. The WebmState maintains a map from cluster byte offsets to their timestamp base; a miss means the block being decoded belongs to a cluster whose offset was never registered during structure parsing.

Source

Thrown at packages/media-parser/src/containers/webm/get-sample-from-block.ts:154

	}

	const timecodeRelativeToCluster = iterator.getInt16();

	const {keyframe} = parseBlockFlags(
		iterator,
		ebml.type === 'SimpleBlock'
			? matroskaElements.SimpleBlock
			: matroskaElements.Block,
	);

	const {codec, trackTimescale} = webmState.getTrackInfoByNumber(trackNumber);

	const clusterOffset = webmState.getTimestampOffsetForByteOffset(offset);

	const timescale = webmState.getTimescale();

	if (clusterOffset === undefined) {
		throw new Error('Could not find offset for byte offset ' + offset);
	}

	// https://github.com/hubblec4/Matroska-Chapters-Specs/blob/master/notes.md/#timestampscale
	// The TimestampScale Element is used to calculate the Raw Timestamp of a Block. The timestamp is obtained by adding the Block's timestamp to the Cluster's Timestamp Element, and then multiplying that result by the TimestampScale. The result will be the Block's Raw Timestamp in nanoseconds.
	const timecodeInNanoSeconds =
		(timecodeRelativeToCluster + clusterOffset) *
		timescale *
		(trackTimescale ?? 1);

	// Timecode should be in microseconds
	const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;

	if (!codec) {
		throw new Error(`Could not find codec for track ${trackNumber}`);
	}

	const remainingNow = ebml.value.length - iterator.counter.getOffset();

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Avoid seeking past unprocessed cluster boundaries — let the parser iterate sequentially, or seek only to offsets the controller has already reported.
  2. Ensure the full structure (all Cluster headers) is available before random access; for WebM this usually means a complete, non-streamed source.
  3. Re-mux the file so cluster timestamps are well-formed: `ffmpeg -i in.webm -c copy out.webm`.
  4. Catch and degrade gracefully — the timestamp cannot be recovered for this block.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await parseMedia({ src, fields: { samples: true }, controller });
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Could not find offset for byte offset')) {
    // A block's byte offset is not in the cluster-timestamp map.
    // Most often caused by seeking past unprocessed cluster headers.
    console.warn('Cluster offset miss — avoid seeking past unprocessed clusters.');
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: Decoding a Block/SimpleBlock at a byte `offset` that does not correspond to any Cluster element header the parser has seen. Happens when cluster boundaries are skipped, when the parser is used with a controller that seeks past clusters, or when the structure pass missed a Cluster due to truncation/corruption.

Common situations: Using a `mediaParserController` to seek into a region before its cluster header was parsed; forward-seeking past unprocessed clusters; files where Cluster Timecode elements are malformed so the offset map isn't populated.

Related errors


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