pandas-dev/pandas · error · NotImplementedError
' ' nodes are not implemented
Error message
'{node_name}' nodes are not implemented What it means
Raised by the auto-generated visit_<NodeName> methods created via the @disallow decorator and _node_not_implemented factory. When the AST visitor encounters a Python syntax node that pandas explicitly does not support in eval/query expressions (e.g., Lambda, IfExp/ternary, GeneratorExp/list comprehension, Set, Dict, Yield, Is/IsNot), the corresponding visit method raises NotImplementedError naming the node. The unsupported set is defined in _unsupported_nodes and _unsupported_expr_nodes (expr.py:224-250).
Solutions
- Rewrite the expression using supported constructs: replace ternary with np.where outside eval; replace 'is None' with isna(); avoid comprehensions and lambdas inside the string.
- Move the unsupported logic out of the eval string into regular Python operating on the result of eval.
- Switch to engine='python' only if the node is supported by the python parser — but most unsupported nodes (Lambda, GeneratorExp, Set) are blocked at the parser/visitor level for both engines.
Example fix
// before
df.query('col > 0 if col else 0')
// after
import numpy as np
df['result'] = np.where(df['col'] > 0, df['col'], 0) Defensive patterns
Strategy: validation
Validate before calling
import ast
UNSUPPORTED = {'Lambda','IfExp','GeneratorExp','ListComp','SetComp','DictComp','Set','Dict','Yield','Repr','Is','IsNot'}
def check_expr_nodes(expr: str):
tree = ast.parse(expr, mode='eval')
for node in ast.walk(tree):
if type(node).__name__ in UNSUPPORTED:
raise NotImplementedError(f'{type(node).__name__} not supported in eval')
check_expr_nodes(expr)
df.eval(expr) Try / catch
try:
df.eval(expr)
except NotImplementedError as e:
if 'nodes are not implemented' in str(e):
# fall back to regular Python ops on columns
... Prevention
- Restrict eval strings to arithmetic, comparison, and boolean ops.
- Use np.where, isna(), and regular Python for ternary/null/lambda logic.
- Avoid 'is'/'is not' — use isna()/notna() for null checks.
When it happens
Trigger: Calling df.query('col > 0 if col else 0') (IfExp ternary — unsupported); df.eval('(x for x in col)') (GeneratorExp); df.eval('lambda x: x') (Lambda); df.query('a is None') (Is/IsNot — unsupported, use isna() instead); df.eval('{1,2,3}') (Set literal).
Common situations: Writing Python-native expressions inside query/eval that use language features pandas does not model; expecting full Python semantics from a restricted expression DSL.
Related errors
- keyword error in function call
- cannot evaluate scalar only bool ops
- Function " " does not support keyword arguments
- Invalid function call
- N-dimensional objects, where N > 2, are not supported with…
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/adad58cb58425bec.
Report an issue: GitHub.
Appendix: 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 3b7651241d)