HKUDS/Vibe-Trading · error · CashFlowIngestError

{path} row {row_number}: amount is blank. A missing amount m

Error message

{path} row {row_number}: amount is blank. A missing amount must be fixed at the source; it is not treated as zero.

What it means

Raised by _parse_amount when the amount cell is empty after stripping. The library deliberately does not treat missing amounts as zero — silently defaulting to 0 would corrupt totals — so a blank amount must be corrected in the source file or mapped away.

Source

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

    ``(1,234.50)``.

    Args:
        raw: Raw cell text.
        path: File path, used only for error messages.
        row_number: 1-based data row number, used only for error messages.
        decimal_separator: Declared decimal separator, or ``None`` to infer.

    Returns:
        The parsed float, negated when the cell was parenthesised or carried a
        trailing minus.

    Raises:
        CashFlowIngestError: If the cell is blank, not numeric, or ambiguously
            grouped.
    """
    text = (raw or "").strip()
    if not text:
        raise CashFlowIngestError(
            f"{path} row {row_number}: amount is blank. A missing amount must be "
            "fixed at the source; it is not treated as zero."
        )

    negative = text.startswith("(") and text.endswith(")")
    if negative:
        text = text[1:-1]
    text = "".join(ch for ch in text if ch not in _AMOUNT_SYMBOLS).strip()
    if text.endswith("-"):  # trailing-minus exports
        text = "-" + text[:-1]

    try:
        value = float(_to_plain_number(text, decimal_separator))
    except ValueError as exc:
        raise CashFlowIngestError(
            f"{path} row {row_number}: amount {raw!r} is not usable: {exc}"
        ) from exc
    return -value if negative else value

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Open the file at the reported row and fill in or delete the blank-amount row
  2. Verify the delimiter and column mapping are correct so the amount column is actually the amount column
  3. Drop trailing blank rows in the source export
  4. If blanks are legitimately ignorable rows, filter them out of the file before loading

Example fix

# before (row: 2024-01-05,,USD)
load_cashflows('flows.csv')
# after (row: 2024-01-05,150.00,USD)
load_cashflows('flows.csv')
Defensive patterns

Strategy: validation

Validate before calling

blank = [i for i, r in enumerate(rows, 2) if not (r.get(amount_col) or '').strip()]
if blank:
    raise ValueError(f'blank amounts at rows {blank}; fix source')

Type guard

def has_blank_amounts(rows, amount_col) -> bool:
    return any(not (r.get(amount_col) or '').strip() for r in rows)

Try / catch

try:
    load_cashflows(p)
except CashFlowIngestError as e:
    if 'amount is blank' in str(e):
        rows = drop_blank_amount_rows(read_rows(p)); rewrite(p, rows)

Prevention

When it happens

Trigger: load_cashflows (or load_panel via _parse_panel_amount) reads a row whose amount column cell is empty or whitespace-only, e.g. '2024-01-05,,USD'.

Common situations: Sparse spreadsheets where some rows leave the amount blank; header/offset misalignment after a wrong delimiter so amounts land in another column; trailing empty rows picked up by the reader; amount column mapped to the wrong header.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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