HKUDS/Vibe-Trading · error · ValueError

only numeric constants are allowed

Error message

only numeric constants are allowed

What it means

The tool evaluates user-supplied arithmetic expressions by walking the AST and only allows numeric int/float constants (bools explicitly rejected since bool subclasses int) plus a whitelist of binary operators. Any non-numeric constant — strings, None, True/False — raises this ValueError, preventing code injection and type confusion in exact arithmetic.

Source

Thrown at agent/src/tools/financial_rigor_tool.py:99

    return f"{value:,.2f}"


def _eval_arith_node(node: ast.AST) -> Decimal:
    """Recursively evaluate an arithmetic AST node in the Decimal domain.

    Args:
        node: An AST node from a parsed expression.

    Returns:
        The exact Decimal value of the node.

    Raises:
        ValueError: If the node is not a supported numeric/arithmetic form.
    """
    if isinstance(node, ast.Constant):
        # bool is a subclass of int — reject it explicitly.
        if isinstance(node.value, bool) or not isinstance(node.value, (int, float)):
            raise ValueError("only numeric constants are allowed")
        return _exact(node.value)
    if isinstance(node, ast.BinOp):
        op_fn = _AST_BINOPS.get(type(node.op))
        if op_fn is None:
            raise ValueError(f"unsupported operator: {type(node.op).__name__}")
        return op_fn(_eval_arith_node(node.left), _eval_arith_node(node.right))
    if isinstance(node, ast.UnaryOp):
        op_fn = _AST_UNARYOPS.get(type(node.op))
        if op_fn is None:
            raise ValueError(f"unsupported unary operator: {type(node.op).__name__}")
        return op_fn(_eval_arith_node(node.operand))
    raise ValueError(f"disallowed element in expression: {type(node).__name__}")


def _safe_arith(expr: str) -> Decimal:
    """Evaluate a numeric arithmetic expression in the exact-Decimal domain.

    The expression is parsed and evaluated recursively with Decimal arithmetic,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Ensure the expression contains only bare numeric literals and whitelisted operators
  2. Remove quotes around numbers ('2' -> 2) and replace True/False with 1/0 if arithmetic is intended
  3. Pre-validate the expression string with a regex/ast scan allowing only Constant(int/float) and whitelisted BinOps before evaluation

Example fix

# before
_safe_arith("100 * '2'")   # string constant -> ValueError
_safe_arith("price * 1.1")  # names are not constants
# after
_safe_arith("100 * 2")
_safe_arith("110.00000000000001")
Defensive patterns

Strategy: validation

Validate before calling

import ast, re

NUM_EXPR = re.compile(r"^[\d\s.()+\-*/%]+$$")

def looks_safe(expr: str) -> bool:
    if not NUM_EXPR.match(expr):
        return False
    try:
        tree = ast.parse(expr, mode="eval")
    except SyntaxError:
        return False
    return all(
        isinstance(n, (ast.Expression, ast.BinOp, ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod, ast.USub, ast.UAdd, ast.Load))
        or (isinstance(n, ast.Constant) and isinstance(n.value, (int, float)) and not isinstance(n.value, bool))
        for n in ast.walk(tree)
    )

Type guard

def is_numeric_literal(node: ast.AST) -> bool:
    return (
        isinstance(node, ast.Constant)
        and not isinstance(node.value, bool)
        and isinstance(node.value, (int, float))
    )

Try / catch

try:
    value = _safe_arith(expr)
except ValueError as exc:
    if "only numeric constants" in str(exc):
        expr = re.sub(r"'([\d.]+)'", r"\1", expr)  # unquote numeric strings
        value = _safe_arith(expr)
    else:
        raise

Prevention

When it happens

Trigger: Passing an expression containing a string literal like 100 * '2', booleans like True + 1, None, or any non-AST-constant numeric form into _safe_arith; unsupported operators raise a sibling error instead.

Common situations: LLM-generated formulas quoting numbers as strings; formulas using boolean flags; users pasting full Python expressions (variables, function calls) that reach the constant check via unexpected node types.

Related errors


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