mifi/lossless-cut · error · UserFacingError

No rows found

Error message

No rows found

What it means

Thrown by parseCsv() in edlFormats.ts when csvParse() returns a rows array of length 0. This is a UserFacingError raised before any row mapping happens, signalling that the supplied CSV string contained no parseable rows at all. It is a hard precondition gate: the function refuses to produce an empty segment list because every downstream consumer (EDL import, segment loading) assumes at least one row.

Solutions

  1. Verify the CSV file actually contains data: open it in a text editor and confirm there is at least one non-empty line before importing.
  2. Ensure the file is genuinely CSV (comma-separated) and not a different format saved with a .csv extension; re-export from the source tool.
  3. If generating CSV programmatically, guard the parseCsv call by checking the trimmed string is non-empty first.
  4. Catch UserFacingError at the import call site and show the user a friendly 'this CSV appears to be empty' message instead of crashing.

Example fix

// before
const segments = parseCsv(text, parseCsvTime);

// after
if (text.trim() === '') throw new Error('CSV file is empty');
const segments = parseCsv(text, parseCsvTime);
Defensive patterns

Strategy: validation

Validate before calling

// Run before parseCsv
export function assertCsvHasRows(csvStr: string): void {
  const trimmed = csvStr.trim();
  if (trimmed === '') {
    throw new Error('CSV content is empty; nothing to import.');
  }
}
// usage
assertCsvHasRows(text);
const segments = parseCsv(text, parseCsvTime);

Try / catch

try {
  const segments = parseCsv(text, parseCsvTime);
} catch (err) {
  if (err instanceof UserFacingError && /No rows found/.test(err.message)) {
    showError('The selected CSV file is empty.');
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling parseCsv(csvStr, parseTimeFn) with an empty string, a string of only whitespace/newlines, or a CSV whose sole content is a single comma-less blank line that csvParse collapses to zero rows. Also triggered when a user imports a file that has a .csv extension but is actually empty or binary garbage that the parser drops entirely.

Common situations: Exporting an EDL/CSV from another NLE that wrote a 0-byte file; selecting the wrong file in the import dialog; a file truncated by a failed download or sync; copy-pasting only the header-less空白 or a stray BOM/whitespace into the CSV import field.

Related errors


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

Appendix: source

Thrown at src/renderer/src/edlFormats.ts:61

  return parsed?.time;
}

export const getFrameValParser = (fps: number) => (str: string) => {
  if (str === '') return undefined;
  const frameCount = parseFloat(str);
  return getTimeFromFrameNum(fps, frameCount);
};

const csvHeader = [
  'Start',
  'End',
  'Name',
] as const;

export function parseCsv(csvStr: string, parseTimeFn: (a: string) => number | undefined) {
  const rows: string[][] = csvParse(csvStr, {});

  if (rows.length === 0) throw new UserFacingError(i18n.t('No rows found'));
  invariant(rows.every((row) => row.length > 0), 'One row had no columns.');

  // from header
  let tagsKeys: string[] | undefined;

  const mapped = rows.flatMap(([start, end, name, ...tagsColumns], rowIndex) => {
    invariant(start != null, `Row ${rowIndex + 1} has no start time`);

    if (rowIndex === 0
      && start === csvHeader[0]
      && (end == null || end === csvHeader[1])
      && (name == null || name === csvHeader[2])
    ) {
      if (end === csvHeader[1] && name === csvHeader[2]) {
        tagsKeys = tagsColumns.map((tag) => tag.trim());
      }
      // skip header row
      return [];

View on GitHub (pinned to 3b9a59c288)