{"record":{"id":"bbdc2b442f2d2557","repo":"mifi/lossless-cut","slug":"unsupported-file","errorCode":null,"errorMessage":"Unsupported file","messagePattern":"Unsupported file","errorType":"exception","errorClass":"UnsupportedFileError","httpStatus":null,"severity":"error","filePath":"src/renderer/src/ffmpeg.ts","lineNumber":357,"sourceCode":"      decoded = new TextDecoder().decode(stdout);\n      parsedJson = JSON.parse(decoded);\n    } catch {\n      console.log('ffprobe stdout:', decoded ?? stdout);\n      throw new Error('ffprobe returned malformed data');\n    }\n    const { format, chapters = [] } = parsedJson;\n    invariant(format != null);\n\n    const streams = (parsedJson.streams ?? []).map((s) => {\n      if (/DJI_[^/\\\\]+SRT$/.test(filePath)) {\n        return { ...s, guessedType: 'dji-gps-srt' as const };\n      }\n      return { ...s, guessedType: undefined };\n    });\n    return { format, streams, chapters };\n  } catch (err) {\n    if (isExecaError(err) && err.code == null && err.exitCode != null) {\n      throw new UnsupportedFileError('Unsupported file', { cause: err });\n    }\n    throw err;\n  }\n}\n\nexport type FileFfprobeMeta = Awaited<ReturnType<typeof readFileFfprobeMeta>>;\nexport type FileStream = FileFfprobeMeta['streams'][number];\n\nasync function renderThumbnail(filePath: string, timestamp: number, signal: AbortSignal) {\n  const args = [\n    '-ss', String(timestamp),\n    '-i', filePath,\n    '-vf', 'scale=-2:200',\n    '-f', 'image2',\n    '-vframes', '1',\n    '-q:v', '10',\n    '-',\n  ];","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/mifi/lossless-cut/blob/3b9a59c288bf6e11076b583c932cfa48ddab3b02/src/renderer/src/ffmpeg.ts#L339-L375","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst meta = await readFileFfprobeMeta(filePath);\n\n// after\ntry {\n  const meta = await readFileFfprobeMeta(filePath);\n} catch (err) {\n  if (err instanceof UnsupportedFileError) {\n    throw new Error(`ffprobe could not read '${filePath}'. Is it a valid media file?`, { cause: err });\n  }\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"import { UnsupportedFileError } from '../../errors';\nconst isUnsupportedFileError = (err: unknown): err is UnsupportedFileError =>\n  err instanceof UnsupportedFileError;","tryCatchPattern":"import { UnsupportedFileError } from '../../errors';\ntry {\n  const meta = await readFileFfprobeMeta(filePath);\n} catch (err) {\n  if (err instanceof UnsupportedFileError) {\n    showError(`'${filePath}' is not a supported media file.`, err.cause);\n    return null;\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["ffmpeg","ffprobe","file-format","io","user-input"],"backgroundTag":null,"analyzedSha":"3b9a59c288bf6e11076b583c932cfa48ddab3b02","analyzedAt":"2026-08-12T20:54:25.651Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}