HKUDS/Vibe-Trading · error · PanelIngestError

{path}: column header {column_name!r} is not a usable date (

Error message

{path}: column header {column_name!r} is not a usable date ({exc}); wide_entities_rows requires every column after the first to be a date, or pass layout='long' with columns=... instead

What it means

In wide_entities_rows layout every column after the first must be a date header; this wraps the date-parse failure and suggests either fixing the headers or using layout='long' with columns=... instead.

Source

Thrown at agent/src/entities/ingest.py:1124

        )
    if len(header) < 2:
        raise PanelIngestError(
            f"{path}: layout={layout!r} needs at least one column besides "
            f"the first (row-label) column. Columns present: {', '.join(header)}"
        )

    row_label_column = header[0]
    series_columns = list(header[1:])

    column_dates: dict[str, date] = {}
    if layout == "wide_entities_rows":
        for column_name in series_columns:
            try:
                column_dates[column_name] = _parse_panel_date(
                    column_name, date_format, path, row_number=0
                )
            except PanelIngestError as exc:
                raise PanelIngestError(
                    f"{path}: column header {column_name!r} is not a usable "
                    f"date ({exc}); wide_entities_rows requires every column "
                    "after the first to be a date, or pass layout='long' "
                    "with columns=... instead"
                ) from exc

    observations: list[PanelObservation] = []
    for offset, row in enumerate(rows):
        row_number = offset + 1
        if all(not (value or "").strip() for value in row.values()):
            continue  # trailing blank line

        row_label_raw = (row.get(row_label_column) or "").strip()
        if not row_label_raw:
            raise PanelIngestError(f"{path} row {row_number}: {row_label_column!r} is blank")

        row_date = (
            _parse_panel_date(row_label_raw, date_format, path, row_number)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass an explicit date_format matching the headers (e.g. '%b %Y')
  2. Remove/ignore non-date summary columns from the file
  3. Switch to layout='long' with columns=... to map columns explicitly

Example fix

# before
panel = load_panel('wide.csv', metric='m', currency='USD', unit='u')
# after
panel = load_panel('wide.csv', metric='m', currency='USD', unit='u', date_format='%b %Y')
Defensive patterns

Strategy: try-catch

Validate before calling

for h in header[1:]:
    try: date.fromisoformat(h)
    except ValueError: print('non-date column:', h)

Try / catch

except PanelIngestError as e:
    if 'not a usable date' in str(e): retry with date_format=... or layout='long'

Prevention

When it happens

Trigger: load_panel inferring/explicitly using 'wide_entities_rows' where a column header (e.g. 'Total' or 'Q1 2024') is not parseable as a date with the given date_format.

Common situations: Wide tables with summary columns ('Total', 'YoY'), or non-ISO date headers while relying on inference.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/e8b387417baa4cb9. Report an issue: GitHub.