GitHub user eugenegujing created a discussion: Should CSV/JSONL scan fail 
loudly on rows that don't match the inferred schema?

## The problem

Texera's CSV/JSONL scan source operators infer each column's type from only a 
sample of the first ~100 rows (`INFER_READ_LIMIT`). At read time, if a *later* 
row holds a value that doesn't parse as the inferred type, the operator 
currently **silently drops the entire row** — no error, no warning, no 
skipped-row count, nothing in the console. Every downstream count, aggregate, 
join, or model then runs on a silently truncated dataset, and the user has no 
way to know data was lost.

Concrete example: a CSV whose `age` column is integer for the first 100 rows 
(inferred `INTEGER`) but holds `55.5` at row 150. Row 150 is dropped, so a 
403-row file scans as 402 rows — silently. There's also an inconsistency: an 
*empty* cell is kept as `null` (the row survives), but a cell that *fails to 
parse* takes the whole row down. The more destructive path is the quiet one.

Issue: apache/texera#6279 — Proposed fix (PR): apache/texera#6323

## Why I'm raising it here

This is a **behavior change**, so I'd like committer/community input before it 
lands. The proposed fix converts the silent drop into a loud, actionable 
failure:

```
Before:  row fails to parse  ->  caught -> dropped        ->  no signal (silent 
data loss)
After:   row fails to parse  ->  clear console error       ->  run stops
                                  (names row, value, column, expected type)
```

Example of the new message:
> Row 150: value '55.5' in column 'age' cannot be read as INTEGER. Column types 
> were inferred from the first 100 rows of the file, and this value does not 
> match. Fix the value in the file, or clean the data before scanning.

The trade-off: **workflows that currently run to completion on slightly-dirty 
data will start failing on the first bad row.** That's the intended improvement 
(loud > silent), but it *will* be visible to existing users, so I'd rather get 
consensus than surprise anyone.

## What I found looking at other platforms

Before settling on "fail loudly", I did a small investigation into how 
comparable data systems handle the same situation (a sampled/inferred column 
type vs. a later value that doesn't match). The short version: **not one of 
them silently drops whole rows** — Texera's current behavior is the outlier. So 
I modeled the proposed fix on the common default across these systems.

| System | Default on a mismatch | Silent? |
| --- | --- | --- |
| Spark (`FAILFAST`), Polars, DuckDB | **error / abort** | no — fails loudly |
| PostgreSQL 17 `COPY ... ON_ERROR ignore` | skip the row **and report a 
skipped-row count** | no — surfaced |
| DuckDB `ignore_errors` + rejects table | skip, but log each rejected row 
(line, column, reason) | no — surfaced |
| **Texera (today)** | **drop the whole row** | **yes — no signal** |

So the options on the table, all with real precedent:

| Option | Behavior | Precedent |
| --- | --- | --- |
| **Fail loudly** (what the PR does) | abort on the first unparsable row with 
an actionable error | Spark `FAILFAST`, Polars, DuckDB |
| Skip + surface a count | keep dropping, but report the skipped-row count / a 
warning | PostgreSQL 17, DuckDB rejects table |

The inference sampling itself (first 100 rows) is not the bug and isn't changed 
here; the bug is that a mismatch at read time is handled silently.

## Questions / where I'd love feedback

1. If we fail by default, do we want an **opt-in escape hatch** — e.g. a "skip 
malformed rows and report how many" mode, and/or a "sample all rows for 
inference" option (à la Polars `infer_schema_length=None` / DuckDB 
`sample_size=-1`) — so users who knowingly have heterogeneous data can still 
proceed?
2. Apply uniformly across all scan variants (CSV, JSONL, ParallelCSV, csvOld) 
in one change? (The current PR does.)

**Very welcome to discuss — all suggestions and alternative directions are 
appreciated, and I'm happy to revise the PR (#6323) based on whatever consensus 
we reach here.** Thanks!

GitHub link: https://github.com/apache/texera/discussions/6324

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to