nodejs/node · error · UnsupportedOperation

Unsupported arity

Error message

Unsupported arity {len(expr.children)}

What it means

gen_cmake.py supports only unary (1 child) and binary (2 children) expression nodes. After the OPS membership check passes, if the node has neither 1 nor 2 children the code can't decide what to build and raises UnsupportedOperation, signalling a structural problem in the parsed tree rather than silently picking an arity.

Solutions

  1. Inspect the parse tree (print expr.pretty()) to see why the operator got the wrong child count.
  2. If a new arity is intentional, add an explicit branch (e.g. _TernaryExpr) before this final raise.
  3. Fix the input/grammar so the operator only ever has 1 or 2 children.

Example fix

# before: grammar allows ternary `cond ? a : b` as one operator node
# after: rewrite as nested binary (cond AND a) OR b, or add a _TernaryExpr branch
Defensive patterns

Strategy: type-guard

Validate before calling

n = len(expr.children)
assert n in (1,2), f'operator {expr.data} has unsupported arity {n}'

Type guard

def is_supported_arity(expr):
    return len(expr.children) in (1, 2)

Prevention

When it happens

Trigger: Raised in _Expr() when `len(expr.children)` is neither 1 nor 2 for a valid operator node. Fires after the unary/binary branches, so it's the catch-all for 0-child or 3+-child operator nodes.

Common situations: Grammar rule change that lets an operator take a variable/tuple arity (e.g. ternary) without a corresponding builder; malformed input that lark parsed into an unexpected tree shape; hand-edited parse tree in tests.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/fb905b9ab8e8000b. Report an issue: GitHub.

Appendix: source

Thrown at deps/v8/tools/cppgc/gen_cmake.py:190

        'Post-order traverse expression trees'
        if isinstance(expr, lark.Token):
            if expr.type == 'IDENTIFIER':
                return self.builder.BuildIdentifier(str(expr))
            elif expr.type == 'INTEGER':
                return self.builder.BuildInteger(str(expr))
            else:
                return self.builder.BuildString(str(expr))
        if expr.data == 'par_expr':
            return self.builder.BuildParenthesizedOperation(
                self._Expr(*expr.children))
        if expr.data not in OPS:
            raise UnsupportedOperation(
                f'The operator "{expr.data}" is not supported')
        if len(expr.children) == 1:
            return self._UnaryExpr(expr.data, *expr.children)
        if len(expr.children) == 2:
            return self._BinaryExpr(expr.data, *expr.children)
        raise UnsupportedOperation(f'Unsupported arity {len(expr.children)}')

    def _UnaryExpr(self, op, right):
        right = self._Expr(right)
        return self.builder.BuildUnaryOperation(op, right)

    def _BinaryExpr(self, op, left, right):
        left = self._Expr(left)
        right = self._Expr(right)
        return self.builder.BuildBinaryOperation(left, op, right)

    STATEMENTS = {
        'assignment': _Assignment,
        'condition': _Condition,
    }

    ASSIGN_TYPES = {
        'asgn_op': _AssignEq,
        'asgn_add_op': _AssignAdd,

View on GitHub (pinned to 1b2de5e052)