Skip to content

data ingest/validate don't validate --schema column TYPE tokens locally — bad types escape the exit-2 gate #213

Description

@LukasWodka

Found during functional review of the data-ingest flow on develop (2026-07-10).

What

The --schema col:TYPE override (and the schema field in an ingest.yaml) is not type-validated locally. A bogus SQL type token sails past every local preflight check:

  • tracebloc data validate <spec with schema {age:NOTATYPE, label:totally_fake_type}> → prints <file>: ok and exits 0.
  • tracebloc data ingest <csv> --task tabular_classification --label-column label --schema age:NOTATYPE --dry-run --no-input → passes all local checks, reaches "Connecting to your workspace…", exit 3 (kubeconfig only) — byte-identical local flow to a valid age:INT.

Only malformed syntax is caught (age: / age=INT → exit 2 "must be col:TYPE"); the TYPE token itself is never checked.

Why it matters

Defeats the CLI's "fail fast, fail local" design for the manual override path: the dedicated millisecond preflight tool (data validate) gives a false green, and data ingest burns a full upload before the in-cluster ingestor rejects the type. The documented exit-2 "schema validation failed" contract is bypassed.

Where

  • internal/push/tabular.go:231ParseSchema passes the TYPE through verbatim (its docstring explicitly defers type-checking to the in-cluster ingestor).
  • internal/schema/ingest.v1.json:130-137 — the embedded schema constrains each schema value only to type:string, no enum/pattern.
  • Shared by the interactive path via internal/cli/interactive.go:471 (validateOptionalSchema).

Fix direction (care needed)

Validate the TYPE token locally and return exit 2 on an unknown type. Do not naively enum the --help shortlist — the ingestor accepts more than that (INTEGER is a valid MySQL synonym of INT; TIMESTAMP/TIME/TEXT are supported per ParseSchema's own docstring). Mirror the ingestor's real accepted type grammar (the di#349 parity source is the authority) so valid synonyms aren't over-rejected.

Scope

Only affects the explicit --schema path; the default inferred-schema path (di#349) always emits valid types, so the common case is unaffected. Worst locally-provable cost is a wasted cluster round-trip.

Severity: MED. Verified via adversarial re-run on the real develop binary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions