google/python-fire · warning · ValueError

{value}

Error message

{value}

What it means

Python Fire's _LiteralEval raises ValueError when a command-line value parses to an AST whose top-level node is a BinOp (an arithmetic/comparison expression like `1+2` or `a-b`). Fire deliberately rejects expressions so they are never evaluated; the public DefaultParseValue catches this ValueError and falls back to treating the value as a plain string. The error only surfaces if you call _LiteralEval (or the parser internals) directly.

Source

Thrown at fire/parser.py:100

  First the AST of the value is updated so that bare-words are turned into
  strings. Then the resulting AST is evaluated as a literal or container of
  only containers and literals.

  This allows for the YAML-like syntax {a: b} to represent the dict {'a': 'b'}

  Args:
    value: A string to be parsed as a literal or container of containers and
      literals.
  Returns:
    The Python value representing the value arg.
  Raises:
    ValueError: If the value is not an expression with only containers and
      literals.
    SyntaxError: If the value string has a syntax error.
  """
  root = ast.parse(value, mode='eval')
  if isinstance(root.body, ast.BinOp):
    raise ValueError(value)

  for node in ast.walk(root):
    for field, child in ast.iter_fields(node):
      if isinstance(child, list):
        for index, subchild in enumerate(child):
          if isinstance(subchild, ast.Name):
            child[index] = _Replacement(subchild)

      elif isinstance(child, ast.Name):
        replacement = _Replacement(child)
        setattr(node, field, replacement)

  # ast.literal_eval supports the following types:
  # strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None
  # (bytes and set literals only starting with Python 3.2)
  return ast.literal_eval(root)

View on GitHub (pinned to 716bbc23d7)

Solutions

  1. Use fire.parser.DefaultParseValue instead of _LiteralEval; it catches this ValueError and returns the value as a string.
  2. If you need computed values, do the arithmetic in your own component or accept the value as a string and parse it yourself.
  3. Pass a plain literal (e.g. '6' instead of '5+1') on the command line.
  4. Wrap direct _LiteralEval calls in try/except (ValueError, SyntaxError) and fall back to the raw string, mirroring DefaultParseValue.

Example fix

// before
from fire.parser import _LiteralEval
value = _LiteralEval('1+2')  # ValueError

// after
from fire.parser import DefaultParseValue
value = DefaultParseValue('1+2')  # returns the string '1+2'
Defensive patterns

Strategy: validation

Validate before calling

import ast

def is_safe_literal(value):
    try:
        root = ast.parse(value, mode='eval')
    except SyntaxError:
        return False
    return not isinstance(root.body, ast.BinOp)

# call _LiteralEval only when is_safe_literal(value) is True

Type guard

import ast

def is_eval_safe_literal(value: str) -> bool:
    try:
        root = ast.parse(value, mode='eval')
    except (SyntaxError, ValueError):
        return False
    return not isinstance(root.body, ast.BinOp)

Try / catch

try:
    parsed = fire.parser._LiteralEval(value)
except (ValueError, SyntaxError):
    parsed = value  # fall back to raw string, as DefaultParseValue does

Prevention

When it happens

Trigger: Calling fire.parser._LiteralEval('1+2') (or DefaultParseValue's internals bypassed) with a string whose eval-mode AST root is ast.BinOp, e.g. '3*4', 'x-y', '(1,2)+(3,4)'. Also triggered when Fire code paths that expect a literal call _LiteralEval instead of DefaultParseValue.

Common situations: Users pass arithmetic like '--count=5+1' expecting Fire to compute it; Fire instead treats '5+1' as the string '5+1'. Developers testing or reusing Fire's parser directly hit the raw ValueError when they assume it behaves like ast.literal_eval with expression support.

Related errors


AI-assisted analysis of google/python-fire@716bbc23d7 (2026-08-28). Data as JSON: /api/errors/07c215caa0e36d1c. Report an issue: GitHub.