mifi/lossless-cut · error · UnsupportedFileError
Unsupported file
Error message
Unsupported file
What it means
Thrown by readFileFfprobeMeta() when the underlying ffprobe child process fails with an execa error that has a null `code` (process not spawned/missing) but a non-null `exitCode` (ffprobe ran and exited non-zero). The original error is wrapped in an UnsupportedFileError so callers can distinguish 'ffprobe rejected this file' from genuine I/O or spawn failures. It signals ffprobe could not demux or read the container/format.
Source
Thrown at src/renderer/src/ffmpeg.ts:357
decoded = new TextDecoder().decode(stdout);
parsedJson = JSON.parse(decoded);
} catch {
console.log('ffprobe stdout:', decoded ?? stdout);
throw new Error('ffprobe returned malformed data');
}
const { format, chapters = [] } = parsedJson;
invariant(format != null);
const streams = (parsedJson.streams ?? []).map((s) => {
if (/DJI_[^/\\]+SRT$/.test(filePath)) {
return { ...s, guessedType: 'dji-gps-srt' as const };
}
return { ...s, guessedType: undefined };
});
return { format, streams, chapters };
} catch (err) {
if (isExecaError(err) && err.code == null && err.exitCode != null) {
throw new UnsupportedFileError('Unsupported file', { cause: err });
}
throw err;
}
}
export type FileFfprobeMeta = Awaited<ReturnType<typeof readFileFfprobeMeta>>;
export type FileStream = FileFfprobeMeta['streams'][number];
async function renderThumbnail(filePath: string, timestamp: number, signal: AbortSignal) {
const args = [
'-ss', String(timestamp),
'-i', filePath,
'-vf', 'scale=-2:200',
'-f', 'image2',
'-vframes', '1',
'-q:v', '10',
'-',
];View on GitHub (pinned to 3b9a59c288)
Solutions
- Confirm the file is a valid, complete media container using `ffprobe -i <file>` directly and read its stderr.
- If the file is truncated or corrupt, re-download or re-mux it (`ffmpeg -i in -c copy out`).
- Upgrade the bundled ffprobe/ffmpeg to a build with the required demuxer/decoder enabled.
- Catch UnsupportedFileError at the call site and prompt the user to pick a supported file.
Example fix
// before
const meta = await readFileFfprobeMeta(filePath);
// after
try {
const meta = await readFileFfprobeMeta(filePath);
} catch (err) {
if (err instanceof UnsupportedFileError) {
throw new Error(`ffprobe could not read '${filePath}'. Is it a valid media file?`, { cause: err });
}
throw err;
} Defensive patterns
Strategy: try-catch
Type guard
import { UnsupportedFileError } from '../../errors';
const isUnsupportedFileError = (err: unknown): err is UnsupportedFileError =>
err instanceof UnsupportedFileError; Try / catch
import { UnsupportedFileError } from '../../errors';
try {
const meta = await readFileFfprobeMeta(filePath);
} catch (err) {
if (err instanceof UnsupportedFileError) {
showError(`'${filePath}' is not a supported media file.`, err.cause);
return null;
}
throw err;
} Prevention
- Validate the file is a real media container with `ffprobe -i` before opening.
- Keep the bundled ffmpeg/ffprobe current so demuxers/decoders are available.
- Filter the open dialog to known media extensions to reduce bad inputs.
- Re-mux or re-download truncated/corrupt files before use.
When it happens
Trigger: Calling readFileFfprobeMeta(filePath) on a file ffprobe cannot parse (unknown codec, truncated header, DRM-protected, corrupted moov atom); a path that exists but is not a media container (e.g. a .txt renamed to .mp4); a partially-written file still being recorded.
Common situations: Damaged downloads; files with broken or missing moov/mdat atoms (MP4); encrypted/DRM media; non-media files dragged into the app; outdated ffprobe build lacking a needed demuxer; very large files where ffprobe hit an internal limit.
Related errors
- No rows found
- Invalid start or end value. Must contain a number of seconds
- Less than 2 frames found
- Failed to find next keyframe
- Failed to find any prev frame
AI-assisted analysis of mifi/lossless-cut@3b9a59c288 (2026-08-12).
Data as JSON: /api/errors/bbdc2b442f2d2557.
Report an issue: GitHub.