Validation Layers⚓︎
Not every table problem belongs to the same layer. Understanding the layers makes errors easier to explain and schemas easier to design.
Consider this table:
Given the users exist
| name | age | email | manager |
| Mira | old | mira@example.io | |
| | 29 | mira@example.io | unknown |
It has more than one kind of issue. Each issue should be reported at the layer that understands it best.
Field parsing⚓︎
Field parsing handles one cell becoming one Python value.
Field parser failed: invalid literal for int() with base 10: 'old'
(code=parser_failed, field='age', row=2, column=2, value='old')
This is the right layer for numbers, booleans, choices, dates, lists, and other cell-level syntax.
Required fields⚓︎
Required-field validation answers a simpler question: did the author provide the value the table needs?
Required field has an empty value
(code=empty_required, field='name', row=3, column=1, value='')
This is not a parsing problem. There is no value to parse.
Whole-table rules⚓︎
Some rules require more than one record. Duplicate emails are a table-level concern because no single row can know whether another row used the same email.
References⚓︎
References are another layer. A cell can parse correctly and still point to an item that does not exist.
Reference target 'unknown' was not found
(code=reference_failed, field='manager', row=3, column=4, value='unknown')
The guides show these layers in practice: record validation, whole-table validation, and reference resolution.
Layered errors are easier to fix
If the age is invalid, point to the age cell. If emails are duplicated, explain the table rule. If a reference is missing, point to the reference cell. The reader should not have to guess which kind of mistake they made.