pandas-dev/pandas · error · ValueError
expr must be a string to be evaluated
Error message
expr must be a string to be evaluated, {type(expr)} given What it means
Raised in the public eval() function when expr is an instance of NDFrame (a DataFrame or Series) rather than a string. Passing a DataFrame/Series would otherwise be converted to its (possibly truncated) string repr and parsed, producing a confusing downstream error (see GH#16289). This early guard gives a clear message instead.
Solutions
- Pass an expression string, not a DataFrame: pd.eval('col_a + col_b') with the data supplied via target/local_dict/resolvers.
- If you meant to evaluate in the context of a DataFrame, use df.eval('col_a + col_b').
- Add a type check before the call: assert isinstance(expr, str).
Example fix
// before
result = pd.eval(df)
// after
result = df.eval('col_a + col_b') Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(expr, pd.DataFrame) or isinstance(expr, pd.Series):
raise TypeError('Pass an expression string, not a DataFrame/Series')
pd.eval(expr) Type guard
import pandas as pd
def is_eval_string(e) -> bool:
return isinstance(e, str) Try / catch
try:
pd.eval(expr)
except ValueError as e:
if 'expr must be a string' in str(e):
# caller passed a DataFrame; redirect to df.eval
... Prevention
- Always pass a string literal or string variable as expr.
- Use df.eval when operating on a DataFrame.
- Add assertions in wrappers to catch type drift.
When it happens
Trigger: Calling pd.eval(df) or pd.eval(some_series) where the first positional argument is a DataFrame or Series rather than an expression string.
Common situations: Refactoring code that previously called df.eval and was changed to pd.eval while leaving the DataFrame as the first argument; passing the wrong variable (the data instead of the expression string); programmatic code that selects between an object and a string and accidentally passes the object.
Related errors
- Cannot assign expression output to target
- Cannot operate inplace if there is no assignment
- expr cannot be an empty string
- Invalid parser ' ' passed, valid parsers are
- multi-line expressions are only valid in the context of…
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/de107e9f40879483.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/computation/eval.py:342
1 pig 20
We can add a new column using ``pd.eval``:
>>> pd.eval("double_age = df.age * 2", target=df)
animal age double_age
0 dog 10 20
1 pig 20 40
"""
inplace = validate_bool_kwarg(inplace, "inplace")
exprs: list[str | BinOp]
if isinstance(expr, str):
_check_expression(expr)
exprs = [e.strip() for e in expr.splitlines() if e.strip() != ""]
elif isinstance(expr, NDFrame):
# GH#16289 a Series/DataFrame would otherwise be converted to its
# (possibly truncated) repr and parsed, producing a confusing error
raise ValueError(f"expr must be a string to be evaluated, {type(expr)} given")
else:
# ops.BinOp; for internal compat, not intended to be passed by users
exprs = [expr]
multi_line = len(exprs) > 1
if multi_line and target is None:
raise ValueError(
"multi-line expressions are only valid in the "
"context of data, use DataFrame.eval"
)
engine = _check_engine(engine)
_check_parser(parser)
_check_resolvers(resolvers)
ret = None
first_expr = True
target_modified = False
View on GitHub (pinned to 3b7651241d)