mifi/lossless-cut · error · UserFacingError

Failed to find any prev keyframe

Error message

Failed to find any prev keyframe

What it means

Thrown by getSafeCutTime() (previous branch) after it has confirmed the index frame's successor is not a keyframe, when the reverse search for a preceding keyframe (time <= cutTime + sigma) yields -1. The function needs a previous keyframe to reposition the cut onto a safe boundary, and none exists earlier in the frame list. This means there is no keyframe at or before the cut at all.

Source

Thrown at src/renderer/src/ffmpeg.ts:188

    return arr.length - 1 - ret;
  };

  index = findReverseIndex(frames, (f) => f.time <= cutTime + sigma);
  if (index === -1) throw new UserFacingError(i18n.t('Failed to find any prev frame'));
  if (index === 0) throw new UserFacingError(i18n.t('We are on the first frame'));

  if (index === frames.length - 1) {
    // Last frame of video, no need to modify cut time
    return undefined;
  }
  if (frames[index + 1]!.keyframe) {
    // Already on frame before keyframe, no need to modify cut time
    return undefined;
  }

  // We are not on a frame before keyframe, look for preceding keyframe instead
  index = findReverseIndex(frames, (f) => f.keyframe && f.time <= cutTime + sigma);
  if (index === -1) throw new UserFacingError(i18n.t('Failed to find any prev keyframe'));
  if (index === 0) throw new UserFacingError(i18n.t('We are on the first keyframe'));

  // Use frame before the found keyframe
  return frames[index - 1]!.time;
}

export function findNearestKeyFrameTime({ frames, time, direction }: { frames: Frame[], time: number, direction: number }) {
  const keyframes = frames.filter((f) => f.keyframe && (direction > 0 ? f.time >= time : f.time <= time));
  if (keyframes.length === 0) return undefined;
  const nearestKeyFrame = sortBy(keyframes, (keyframe) => (direction > 0 ? keyframe.time - time : time - keyframe.time))[0];
  if (!nearestKeyFrame) return undefined;
  return nearestKeyFrame.time;
}

export function tryMapChaptersToEdl(chapters: FFprobeChapter[]) {
  try {
    return chapters.flatMap((chapter) => {
      const start = parseFloat(chapter.start_time);

View on GitHub (pinned to 3b9a59c288)

Solutions

  1. Extend the keyframe/frame probe backward to include the stream's first keyframe (probe from time 0).
  2. If the cut is at the file start, skip smart-cut alignment (cut is already at a safe boundary).
  3. Re-encode the source to guarantee a keyframe at position 0 (-force_key_frames).
  4. Fall back to lossless cut at the requested time when no preceding keyframe exists.

Example fix

// before
const t = getSafeCutTime(frames, cutTime, false);

// after
const hasPrevKeyframe = frames.some((f) => f.keyframe && f.time <= cutTime + 0.01);
const t = hasPrevKeyframe ? getSafeCutTime(frames, cutTime, false) : cutTime;
Defensive patterns

Strategy: validation

Validate before calling

const sigma = 0.01;
const hasPrevKeyframe = frames.some((f) => f.keyframe && f.time <= cutTime + sigma);
if (!hasPrevKeyframe) {
  // no earlier keyframe; cannot align backward
  return undefined;
}

Try / catch

try {
  return getSafeCutTime(frames, cutTime, false);
} catch (err) {
  if (err instanceof UserFacingError && /any prev keyframe/.test(err.message)) {
    return cutTime;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling getSafeCutTime in prev mode where the only keyframe in the list is the one at/after the cut; the frame window was probed starting after the first keyframe; a stream where the very first keyframe sits after the cut point.

Common situations: Cutting at the absolute start of a file (the first keyframe is the only one and it is at/after the cut); a frame probe window that excluded the stream's first keyframe; damaged streams missing their initial IDR frame.

Related errors


AI-assisted analysis of mifi/lossless-cut@3b9a59c288 (2026-08-12). Data as JSON: /api/errors/17ca947d65e9193d. Report an issue: GitHub.