Skip to content

Bug: ParseError should include rowNumber in error details #519

@kamiazya

Description

@kamiazya

Description

When a ParseError occurs, it includes position (line, column, offset) but not the rowNumber. The rowNumber would be more intuitive for users to identify which CSV record failed.

Current Behavior

import { parse, ParseError } from 'web-csv-toolbox';

const csv = `name,age
Alice,42
Bob,"unclosed quote
Charlie,30`;

try {
  await parse.toArray(csv);
} catch (error) {
  if (error instanceof ParseError) {
    console.log(error.position);
    // { line: 3, column: 23, offset: 42 }
    // No rowNumber field!
  }
}

Users need to correlate line with the actual CSV row, which is confusing when:

  • CSV has multi-line quoted fields (line ≠ row)
  • Users think in terms of "row 3" not "line 3"

Expected Behavior

try {
  await parse.toArray(csv);
} catch (error) {
  if (error instanceof ParseError) {
    console.log(error.position);
    // { line: 3, column: 23, offset: 42 }
    console.log(error.rowNumber);
    // 3 (the problematic CSV row)
    console.error(`Error at row ${error.rowNumber}: ${error.message}`);
  }
}

Root Cause

In src/Lexer.ts, when throwing ParseError:

throw new ParseError("Unexpected EOF while parsing quoted field.", {
  position: { ...this.#cursor },
});

The Lexer has #rowNumber available but doesn't include it in the error.

Proposed Fix

1. Update ParseError interface

In src/common/errors.ts:

export interface ParseErrorOptions extends ErrorOptions {
  position?: Position;
  rowNumber?: number;  // Add this
}

export class ParseError extends SyntaxError {
  public position?: Position;
  public rowNumber?: number;  // Add this

  constructor(message?: string, options?: ParseErrorOptions) {
    super(message, { cause: options?.cause });
    this.name = "ParseError";
    this.position = options?.position;
    this.rowNumber = options?.rowNumber;  // Add this
  }
}

2. Update Lexer to include rowNumber

In src/Lexer.ts:274:

throw new ParseError("Unexpected EOF while parsing quoted field.", {
  position: { ...this.#cursor },
  rowNumber: this.#rowNumber,  // Add this
});

3. Update tests

Add test case verifying rowNumber is included in errors.

Benefits

  • Better error messages for users
  • Easier debugging of malformed CSV files
  • More intuitive than line/column for CSV context
  • Consistency with token location which already has rowNumber

Impact

  • Breaking change: No (adding optional field)
  • Backward compatible: Yes (existing code continues to work)

Acceptance Criteria


Bug Fix: Improves error reporting, good first issue!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomersjavascriptPull requests that update Javascript code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions