remotion-dev/remotion · error · Error
No sample found
Error message
No sample found
What it means
Thrown by findKeyframeBeforeTime when no SamplePosition in the provided list satisfies the criteria: it must be a keyframe (sample.isKeyframe) and its composition or decode time in seconds must be <= the requested time. After the loop, videoSample stays null, which means there is no keyframe at or before the seek target. This usually indicates the sample table does not yet cover the requested time, or the file has no keyframes flagged in the time window.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/find-keyframe-before-time.ts:43
const ctsInSeconds = sample.timestamp / timescale + startInSeconds;
const dtsInSeconds = sample.decodingTimestamp / timescale + startInSeconds;
if (!sample.isKeyframe) {
continue;
}
if (!(ctsInSeconds <= time || dtsInSeconds <= time)) {
continue;
}
if (videoByte <= sample.offset) {
videoByte = sample.offset;
videoSample = sample;
}
}
if (!videoSample) {
throw new Error('No sample found');
}
const mediaSection = mediaSections.find(
(section) =>
videoSample.offset >= section.start &&
videoSample.offset < section.start + section.size,
);
if (!mediaSection) {
Log.trace(
logLevel,
'Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.',
videoSample,
);
return null;
}
return videoSample;View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Ensure seek targets are >= the track's startInSeconds; clamp negative or pre-roll seeks to that value.
- If the file has no stss (sync samples) box, re-mux so every I-frame is marked: `ffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4`.
- For fragmented streams, wait for more fragments (this is often transient; retry after the next moof arrives).
- Validate that samplePositions passed in actually contain at least one keyframe before calling findKeyframeBeforeTime.
Example fix
// before
const kf = findKeyframeBeforeTime({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds });
// after
const hasKeyframe = samplePositions.some((s) => s.isKeyframe);
if (!hasKeyframe) {
return null; // not seekable, caller should fall back to linear scan
}
const kf = findKeyframeBeforeTime({
samplePositions,
time: Math.max(time, startInSeconds),
timescale, mediaSections, logLevel, startInSeconds,
}); Defensive patterns
Strategy: validation
Validate before calling
// Validate there is at least one usable keyframe before calling findKeyframeBeforeTime
import type {SamplePosition} from '../../get-sample-positions';
function findableKeyframe(samples: SamplePosition[], time: number, timescale: number, startInSeconds: number): boolean {
return samples.some((s) => {
if (!s.isKeyframe) return false;
const cts = s.timestamp / timescale + startInSeconds;
const dts = s.decodingTimestamp / timescale + startInSeconds;
return cts <= time || dts <= time;
});
} Type guard
import type {SamplePosition} from '../../get-sample-positions';
function hasAnyKeyframe(samples: SamplePosition[]): boolean {
return samples.length > 0 && samples.some((s) => s.isKeyframe);
} Try / catch
try {
const kf = findKeyframeBeforeTime({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds });
} catch (err) {
if (/No sample found/i.test(String(err?.message))) {
// Either wait for more fragments or fall back to a linear scan from byte 0
return { type: 'valid-but-must-wait' } as const;
}
throw err;
} Prevention
- Clamp seek targets to be >= the track's startInSeconds.
- Ensure files have a sync sample (stss) box so isKeyframe is set; re-mux if absent.
- For fragmented streams, retry seeking after the next moof is parsed rather than throwing.
- Before calling findKeyframeBeforeTime, verify at least one keyframe exists in the window.
When it happens
Trigger: Called during seek resolution (progressive or fragmented MP4) when a time falls before the first keyframe, when all keyframes in the available samples have timestamps after the requested time, or when stss (sync sample table) was missing so no sample.isKeyframe is ever true. Also reachable if startInSeconds is set incorrectly, shifting times forward.
Common situations: Seeking to time 0 or a very early time in a stream whose first keyframe sits at a positive offset (edit-list shifts). Live/DASH fragments where the first fragment's tfdt base pushes times above zero. Files with no stss box (parser falls back to marking nothing as keyframe). Requesting a seek beyond the buffered/downloaded range.
Related errors
- Expected stco box in trak box
- no video and no audio tracks
- No moov atom found
- No trak box found
- Expected tkhd box in trak box
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/66fd10fe2414dae9.
Report an issue: GitHub.