Skip to content

storage describe-batch: malformed --from-file crashes with a traceback instead of a validation error #640

Description

@padak

What happens

A --from-file YAML whose tables: (or presumably buckets:/columns:) key is a list instead of a map crashes with an unhandled exception:

AttributeError: 'list' object has no attribute 'items'
  storage_service.py:2535 in describe_batch
    for table_id, desc in tables.items():

Reproduced on released v0.88.0 (uv tool install, macOS):

# wrong: tables is a list of objects
tables:
  - table_id: in.c-test.part_verify_0880
    columns:
      id: Surrogate key
kbagent --json storage describe-batch --project P --from-file ./bad.yaml

The documented schema is three top-level maps (buckets:, tables:, columns:), each keyed by ID — see references/storage-describe-workflow.md. So the input above is genuinely user error. The problem is the failure mode, not the rejection.

Why it matters

--json was passed and the output is not JSON. It is a Rich-rendered traceback on stdout/stderr. Every convention in this repo says a command must answer --json with an envelope — commands catch KeboolaApiError/ConfigError, map them to an exit code, and emit a structured error. A programmatic consumer (the serve REST layer, a scheduled agent task, a CI script) gets an unparseable blob here instead of {"status":"error","error":{"code":"INVALID_ARGUMENT",...}}.

Secondarily, the traceback names tables.items() deep inside the service — it does not tell the author which key of their file is the wrong shape, which is the one thing they need to know.

Expected

Validate the parsed document's shape before the write loop and raise ConfigError / INVALID_ARGUMENT, naming the offending key and the expected shape, e.g.:

tables must be a mapping of table ID to description, got a list. Expected:
tables:\n in.c-sales.orders: All sales orders

Exit 2 (usage), structured error under --json.

Notes

  • Not a regression: this validation gap predates 0.88.0. Surfaced while verifying the storage describe-column writes column descriptions where the MCP server never reads them #624 native-write path live — the correct schema works fine on both Snowflake and BigQuery (table + column descriptions applied and read back).
  • Worth checking buckets: and columns: for the same hole, and a scalar-instead-of-map case.
  • A test per malformed shape would fit alongside the existing describe-batch tests.

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