remotion-dev/remotion · error · Error

No video section defined

Error message

No video section defined

What it means

Thrown by getSeekingByteFromFragmentedMp4 in the fallback branch: after no seeking info matched and the current byte position is reportedly inside a media section, getCurrentMediaSection returns null. This means the mediaSections list does not actually contain the currentPosition even though isByteInMediaSection returned 'in-section' just above — an internal inconsistency, or the section list was mutated between the two checks.

Source

Thrown at packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts:182

			position: currentPosition,
			mediaSections: info.mediaSections,
		}) !== 'in-section'
	) {
		return {
			type: 'valid-but-must-wait',
		};
	}

	Log.trace(
		logLevel,
		'Fragmented MP4 - Inside the wrong video section, skipping to the end of the section',
	);
	const mediaSection = getCurrentMediaSection({
		offset: currentPosition,
		mediaSections: info.mediaSections,
	});
	if (!mediaSection) {
		throw new Error('No video section defined');
	}

	return {
		type: 'intermediary-seek',
		byte: mediaSection.start + mediaSection.size,
	};
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Do not drive a single media-parser instance from multiple concurrent callers; serialize seek/parse operations.
  2. Capture a snapshot of mediaSections and pass the same array to both isByteInMediaSection and getCurrentMediaSection.
  3. Report a media-parser bug if this reproduces on a single-threaded call sequence — include the file and seek time.
  4. Retry the seek; transient if mediaSections is being populated incrementally.

Example fix

// before
await parser.seek(time);

// after
// Serialize seeks and capture section snapshot externally if driving manually
const sections = parser.getSeekingHints?.().mediaSections ?? [];
if (!sections.length) {
  // wait for media sections to be discovered before seeking
  await waitForFirstMdat();
}
await parser.seek(time);
Defensive patterns

Strategy: retry

Validate before calling

// Ensure mediaSections is non-empty and stable before seeking
function hasMediaSections(sections: { start: number; size: number }[]): boolean {
  return Array.isArray(sections) && sections.length > 0;
}

Type guard

import type {MediaSection} from '../../state/video-section';
function currentPositionHasSection(pos: number, sections: MediaSection[]): boolean {
  return sections.some((s) => pos >= s.start && pos < s.start + s.size);
}

Try / catch

try {
  await parser.seek(time);
} catch (err) {
  if (/No video section defined/i.test(String(err?.message))) {
    // mediaSections may still be populating; wait for the next mdat then retry
    await waitForNextMdat();
    return parser.seek(time);
  }
  throw err;
}

Prevention

When it happens

Trigger: Reached only when isByteInMediaSection reported the position is in a section but getCurrentMediaSection (which finds the specific section) returns null. Practically indicates a state mutation race: mediaSections changed between the two reads, or getCurrentMediaSection uses stricter bounds than isByteInMediaSection.

Common situations: Concurrent reads on a parser instance not designed for concurrency. mediaSections being pruned/shifted by another part of the parser between checks. A logic bug where the two helpers disagree on boundary conditions (e.g. inclusive vs exclusive end).

Related errors


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