Validation fails on a customer export¶
Symptoms¶
One of:
typedecide validate export.csvprintserror: ...and exits with status 2. The file could not be loaded.- It prints
Dataset report: NOT USABLE AS GIVENand exits with status 1. The file loaded, and the report containserrorfindings.
Diagnosis¶
The exit status tells you which half of the problem you have.
Exit 2: a load error. The message names the file, the row, the column, the offending value and a fix. Match its opening against this table:
| Message contains | Cause |
|---|---|
has no 'state' column for the state. Its columns are: ... |
Your columns have other names |
has no options column |
No options column and no option_1, option_2, ... columns |
has both a ... column and the wide columns |
Both option shapes are present |
wide option columns numbered [...] with a gap |
option_1, option_3 with no option_2 |
which none of the delimiters ... splits into two or more options |
One options cell uses a separator the others do not |
lists N id(s) but ... lists M option(s) |
option_ids and options do not line up in that row |
has N fields but the header names M |
An unquoted delimiter inside a field, usually a comma in the ticket text |
holds '...', which is not one of this row's options |
The gold answer does not match any option |
header repeats the column name(s) |
Duplicate header |
Cannot infer a format from |
Unrecognised file suffix |
is not valid JSON |
Wrong --format, or a broken line |
Exit 1: report errors. List them:
python - <<'PY'
import json
for f in json.load(open("report.json"))["findings"]:
if f["severity"] == "error":
print(f["code"], len(f["decisions"]), "rows:", f["decisions"][:5])
PY
Fix¶
Load errors¶
-
Different column names. Point at them; do not rename the file:
typedecide validate export.csv \ --col-id "Ticket ID" --col-state "Ticket Body" --col-question "Decision" \ --col-options "Choices" --col-answer "Chosen" --col-group "Case"Column matching is case-insensitive. Quote names containing spaces.
-
Options in an unusual separator. The auto-detected delimiter must split every options cell into two or more parts. Candidates are tried in this order:
||,|,;, tab,,. If your separator is something else, or option text itself contains one of those characters, set it explicitly from Python:from typedecide import load_decisions from typedecide.data import FieldMapping mapping = FieldMapping( state="Ticket Body", question="Decision", options="Choices", answer="Chosen", option_delimiter=" / ", # options written as "Billing / Shipping / Accounts" ) decisions = load_decisions("export.csv", mapping=mapping) -
Too many fields in a row. Re-export with proper CSV quoting, or as TSV. The message shows the start of the extra field, which identifies the unquoted text.
-
Answer is not an option. Accepted forms are the option id, an answer letter, a 0-based index, or the exact option text. Common causes are trailing qualifiers (
Billing (escalated)), a 1-based index column, and a label from an older option set. See the warning about indices in Bring your own data. -
Wrong format guess. Pass
--format csv(orjsonl,json,parquet,hf).
Report errors¶
| Code | Fix |
|---|---|
duplicate_id |
Make the id column unique, or stop mapping it (--col-id) so the loader hashes the content |
no_labels |
The gold is in a column the loader did not look at. Pass --col-answer |
option_set_mismatch |
Rows sharing a criterion key list different option ids. Give the variants distinct keys or make the sets identical. If the customer's option list changed over time, split by period |
contradictory_labels |
Send the listed row ids back for adjudication. If the evidence really differs, the distinguishing text is missing from the state |
single_group |
The group column holds one value, often a tenant or batch id. Map --col-group to the ticket or case id instead |
empty |
The file has a header and nothing else, or a filter removed everything |
Warnings do not fail validation. Read them anyway: every code is explained here.
Do not fix contradictions by deleting one side at random
contradictory_labels means annotators disagreed about identical evidence. Which
label survives decides what the model learns. Get a decision from whoever owns the
policy.
Verify¶
- Exit status is
0and the first line readsDataset report: OK. labelledin the counts line matches the number of labelled rows you expect. A lower figure means some answers were read as blank.- The
label balanceblock shows the classes you expect, under the keys you expect. - Then confirm the data survives the next step:
typedecide split export.csv --out data/ [same flags].