{"record":{"id":"66fd10fe2414dae9","repo":"remotion-dev/remotion","slug":"no-sample-found","errorCode":null,"errorMessage":"No sample found","messagePattern":"No sample found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/find-keyframe-before-time.ts","lineNumber":43,"sourceCode":"\t\tconst ctsInSeconds = sample.timestamp / timescale + startInSeconds;\n\t\tconst dtsInSeconds = sample.decodingTimestamp / timescale + startInSeconds;\n\n\t\tif (!sample.isKeyframe) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!(ctsInSeconds <= time || dtsInSeconds <= time)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (videoByte <= sample.offset) {\n\t\t\tvideoByte = sample.offset;\n\t\t\tvideoSample = sample;\n\t\t}\n\t}\n\n\tif (!videoSample) {\n\t\tthrow new Error('No sample found');\n\t}\n\n\tconst mediaSection = mediaSections.find(\n\t\t(section) =>\n\t\t\tvideoSample.offset >= section.start &&\n\t\t\tvideoSample.offset < section.start + section.size,\n\t);\n\n\tif (!mediaSection) {\n\t\tLog.trace(\n\t\t\tlogLevel,\n\t\t\t'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.',\n\t\t\tvideoSample,\n\t\t);\n\t\treturn null;\n\t}\n\n\treturn videoSample;","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/find-keyframe-before-time.ts#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst kf = findKeyframeBeforeTime({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds });\n\n// after\nconst hasKeyframe = samplePositions.some((s) => s.isKeyframe);\nif (!hasKeyframe) {\n  return null; // not seekable, caller should fall back to linear scan\n}\nconst kf = findKeyframeBeforeTime({\n  samplePositions,\n  time: Math.max(time, startInSeconds),\n  timescale, mediaSections, logLevel, startInSeconds,\n});","handlingStrategy":"validation","validationCode":"// Validate there is at least one usable keyframe before calling findKeyframeBeforeTime\nimport type {SamplePosition} from '../../get-sample-positions';\nfunction findableKeyframe(samples: SamplePosition[], time: number, timescale: number, startInSeconds: number): boolean {\n  return samples.some((s) => {\n    if (!s.isKeyframe) return false;\n    const cts = s.timestamp / timescale + startInSeconds;\n    const dts = s.decodingTimestamp / timescale + startInSeconds;\n    return cts <= time || dts <= time;\n  });\n}","typeGuard":"import type {SamplePosition} from '../../get-sample-positions';\nfunction hasAnyKeyframe(samples: SamplePosition[]): boolean {\n  return samples.length > 0 && samples.some((s) => s.isKeyframe);\n}","tryCatchPattern":"try {\n  const kf = findKeyframeBeforeTime({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds });\n} catch (err) {\n  if (/No sample found/i.test(String(err?.message))) {\n    // Either wait for more fragments or fall back to a linear scan from byte 0\n    return { type: 'valid-but-must-wait' } as const;\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["mp4","isobmff","media-parser","seeking","keyframe"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}