pandas-dev/pandas · error · NotImplementedError
'{node_name}' nodes are not implemented
Error message
'{node_name}' nodes are not implemented What it means
The expression visitor is built with the @disallow decorator (expr.py:346/779) which installs visit_<Node> methods that raise NotImplementedError for an explicit unsupported set (Lambda, Yield, IfExp, DictComp, SetComp, GeneratorExp, Repr, Set, Is, IsNot, plus statement/module/handler nodes). When the AST produced by Python's parse contains any such node, dispatch lands on _node_not_implemented and raises naming the node type. This bounds the eval grammar to what numexpr/pandas can actually compute.
Source
Thrown at pandas/core/computation/expr.py:267
| _unsupported_expr_nodes
) - _hacked_nodes
# we're adding a different assignment in some cases to be equality comparison
# and we don't want `stmt` and friends in their so get only the class whose
# names are capitalized
_base_supported_nodes = (_all_node_names - _unsupported_nodes) | _hacked_nodes
intersection = _unsupported_nodes & _base_supported_nodes
_msg = f"cannot both support and not support {intersection}"
assert not intersection, _msg
def _node_not_implemented(node_name: str) -> Callable[..., None]:
"""
Return a function that raises a NotImplementedError with a passed node name.
"""
def f(self, *args, **kwargs):
raise NotImplementedError(f"'{node_name}' nodes are not implemented")
return f
# should be bound by BaseExprVisitor but that creates a circular dependency:
# _T is used in disallow, but disallow is used to define BaseExprVisitor
# https://github.com/microsoft/pyright/issues/2315
_T = TypeVar("_T")
def disallow(nodes: set[str]) -> Callable[[type[_T]], type[_T]]:
"""
Decorator to disallow certain nodes from parsing. Raises a
NotImplementedError instead.
Returns
-------
callableView on GitHub (pinned to 71959b8cb9)
Solutions
- Rewrite the logic using supported operators (e.g. replace ternary with np.where outside eval).
- Move the unsupported construct into plain Python and feed its result back as a column.
- For None checks, fillna or use a boolean mask instead of 'is' inside query.
Example fix
// before
df.eval('result = a if flag else b')
// after
df['result'] = np.where(df['flag'], df['a'], df['b']) Defensive patterns
Strategy: validation
Validate before calling
import ast
UNSUPPORTED = {
'Lambda', 'Yield', 'GeneratorExp', 'IfExp', 'DictComp',
'SetComp', 'Repr', 'Set', 'Is', 'IsNot',
}
def validate_eval_ast(expr: str) -> None:
tree = ast.parse(expr, mode='eval')
present = {type(n).__name__ for n in ast.walk(tree)}
bad = present & UNSUPPORTED
if bad:
raise NotImplementedError(
f'eval does not support these nodes: {sorted(bad)}'
)
validate_eval_ast(expr) Type guard
import ast
def uses_only_supported_nodes(expr: str) -> bool:
UNSUPPORTED = {
'Lambda', 'Yield', 'GeneratorExp', 'IfExp',
'DictComp', 'SetComp', 'Repr', 'Set', 'Is', 'IsNot',
}
present = {type(n).__name__ for n in ast.walk(ast.parse(expr, mode='eval'))}
return not (present & UNSUPPORTED) Try / catch
try:
df.eval(expr)
except NotImplementedError as e:
if 'nodes are not implemented' in str(e):
# fall back to plain Python computation
df['result'] = eval(compile(ast.parse(expr, mode='eval'), '<eval>', 'eval'), {}, df.to_dict('series'))
else:
raise Prevention
- Avoid ternaries, lambdas, comprehensions, and 'is'/'is not' inside eval strings.
- Pre-compute unsupported constructs in Python and feed results as columns.
- When accepting user expressions, validate the AST against the supported set first.
When it happens
Trigger: df.eval('a if b else c') (IfExp), df.query('a is None') (Is/IsNot), df.eval('lambda x: x') (Lambda), df.eval('(x for x in a)') (GeneratorExp), df.eval('{k: v for ...}') (DictComp).
Common situations: Porting arbitrary Python one-liners into eval strings. Using 'is None' checks in query. Expecting ternary or comprehension support. Upgrading Python versions that emit different AST node names.
Related errors
- only a single expression is allowed
- keyword error in function call '{node.func.id}'
- The '@' prefix is only supported by the pandas parser
- The '@' prefix is not allowed in top-level eval calls. pleas
- expr must be a string to be evaluated, {type(expr)} given
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/adad58cb58425bec.
Report an issue: GitHub.