HKUDS/Vibe-Trading · error · ValueError

uses a single comma and could be either (comma groups…

Error message

{text!r} uses a single comma and could be either {text.replace(',', '')} (comma groups thousands) or {text.replace(',', '.')} (comma is the decimal separator); pass decimal_separator='.' or decimal_separator=',' to say which

What it means

Raised (as ValueError from _to_plain_number) when a numeric cell contains exactly one comma and no dot, making the number ambiguous: '1,234' could be 1234 (thousands grouping) or 1.234 (decimal comma). The library refuses to guess because either interpretation yields a plausible but different number; the caller must disambiguate via decimal_separator.

Solutions

  1. Inspect the raw value cited in the message and determine whether the comma groups thousands or marks decimals
  2. Pass decimal_separator='.' if commas group thousands, or decimal_separator=',' if the comma is the decimal separator
  3. For per-file locales, load each file with its own decimal_separator rather than a global setting
  4. If the file mixes conventions, normalize the source data first

Example fix

# before
flows = load_cashflows('eu_export.csv')
# after
flows = load_cashflows('eu_export.csv', decimal_separator=',')
Defensive patterns

Strategy: validation

Validate before calling

import re

def detect_ambiguous(cell: str) -> bool:
    return cell.count(',') == 1 and '.' not in cell

ambiguous = [r for r in rows if detect_ambiguous(r['amount'])]
if ambiguous:
    raise SystemExit('ambiguous decimals; choose decimal_separator explicitly')

Type guard

def is_unambiguous_number(text: str) -> bool:
    t = text.strip()
    return not (t.count(',') == 1 and '.' not in t)

Try / catch

try:
    load_cashflows(p)
except CashFlowIngestError as e:
    if 'could be either' in str(e):
        load_cashflows(p, decimal_separator=decide_by_locale_of(p))

Prevention

When it happens

Trigger: load_cashflows / _parse_amount encounters a cell like '1,234' or '12,5' and decimal_separator is None. Values with multiple commas ('1,234,567') or with both separators are resolved automatically; only the single-comma/no-dot case raises.

Common situations: European exports with decimal commas ('1234,5' with one digit after) that look like thousands groups; US exports with a single thousands comma ('1,234'); mixed-locale CSVs loaded without configuration.

Related errors


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

Appendix: source

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

        ValueError: If the value uses a single comma whose role cannot be
            determined -- ``"1,234"`` is 1234 in a US export and 1.234 in a
            European one, and the data cannot say which.
    """
    if decimal_separator is not None:
        grouping = "," if decimal_separator == "." else "."
        return text.replace(grouping, "").replace(decimal_separator, ".")

    has_dot = "." in text
    has_comma = "," in text
    if has_dot and has_comma:
        # The rightmost separator is the decimal one; the other groups digits.
        if text.rindex(".") > text.rindex(","):
            return text.replace(",", "")
        return text.replace(".", "").replace(",", ".")
    if has_comma:
        if text.count(",") > 1:
            return text.replace(",", "")  # 1,234,567 cannot be a decimal comma
        raise ValueError(
            f"{text!r} uses a single comma and could be either "
            f"{text.replace(',', '')} (comma groups thousands) or "
            f"{text.replace(',', '.')} (comma is the decimal separator); pass "
            "decimal_separator='.' or decimal_separator=',' to say which"
        )
    return text


def _parse_amount(
    raw: str,
    path: Path,
    row_number: int,
    decimal_separator: str | None = None,
) -> float:
    """Parse a numeric amount from a file field.

    Handles currency symbols, digit grouping, and the accounting convention
    where parentheses or a trailing minus denote a negative number, e.g.

View on GitHub (pinned to 80ffdda44c)