mifi/lossless-cut · error · UserFacingError

Failed to find any prev frame

Error message

Failed to find any prev frame

What it means

Thrown by getSafeCutTime() in the non-next (previous) branch when findReverseIndex returns -1, i.e. no frame in the list has a time <= cutTime + sigma. The function needs the frame at or just before the cut to anchor a previous-keyframe search, so the absence of any preceding frame is fatal. Effectively the cut point lies before the first known frame.

Source

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

    index = frames.findIndex((f) => f.keyframe && f.time >= cutTime - sigma);
    if (index === -1) throw new UserFacingError(i18n.t('Failed to find next keyframe'));
    if (index >= frames.length - 1) throw new UserFacingError(i18n.t('We are on the last frame'));
    const { time } = frames[index]!;
    if (isCloseTo(time, cutTime)) {
      return undefined; // Already on keyframe, no need to modify cut time
    }
    return time;
  }

  const findReverseIndex = <T>(arr: T[], cb: (value: T, i: number, obj: T[]) => unknown) => {
    // eslint-disable-next-line unicorn/no-array-callback-reference
    const ret = [...arr].reverse().findIndex(cb);
    if (ret === -1) return -1;
    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;

View on GitHub (pinned to 3b9a59c288)

Solutions

  1. Ensure the frame probe window includes frames at or before cutTime (probe from 0 or extend the window backward).
  2. Clamp cutTime to >= the first frame's time before calling getSafeCutTime.
  3. If the cut is at the very start, short-circuit: no previous-keyframe adjustment is needed.
  4. Verify timebase/timestamp consistency between the cut clock and the frame probe clock.

Example fix

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

// after
const firstFrameTime = frames[0]?.time ?? 0;
const clamped = Math.max(cutTime, firstFrameTime);
const t = getSafeCutTime(frames, clamped, false);
Defensive patterns

Strategy: validation

Validate before calling

const sigma = 0.01;
const firstFrameTime = frames[0]?.time ?? 0;
if (cutTime < firstFrameTime - sigma) {
  // cut is before any known frame; clamp or skip
  return undefined;
}

Try / catch

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

Prevention

When it happens

Trigger: Calling getSafeCutTime(frames, cutTime, false) where cutTime is earlier than the earliest frame's time; a frames array that only covers a window strictly after the cut point; cutTime clamped/rounded to a value below the first frame timestamp.

Common situations: Probe window starts after the cut; negative or zero cutTime on a stream whose first frame time is positive (timestamp offset); cutting at the very start of a file where the frame list begins later than expected; misaligned time bases between the cut time and the frame probe.

Related errors


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