antlr/antlr4 · error · Exception

tree cannot be null

Error message

tree cannot be null

What it means

ParseTreeMatch is the result object returned by ParseTreePatternMatcher.match(); its constructor requires a non-None parse tree. 'tree cannot be null' fires when a None tree is supplied — normally internally by match(tree, pattern) when the caller passed None as the tree argument.

Source

Thrown at runtime/Python3/src/antlr4/tree/ParseTreeMatch.py:35

    __slots__ = ('tree', 'pattern', 'labels', 'mismatchedNode')
    #
    # Constructs a new instance of {@link ParseTreeMatch} from the specified
    # parse tree and pattern.
    #
    # @param tree The parse tree to match against the pattern.
    # @param pattern The parse tree pattern.
    # @param labels A mapping from label names to collections of
    # {@link ParseTree} objects located by the tree pattern matching process.
    # @param mismatchedNode The first node which failed to match the tree
    # pattern during the matching process.
    #
    # @exception IllegalArgumentException if {@code tree} is {@code null}
    # @exception IllegalArgumentException if {@code pattern} is {@code null}
    # @exception IllegalArgumentException if {@code labels} is {@code null}
    #
    def __init__(self, tree:ParseTree, pattern:ParseTreePattern, labels:dict, mismatchedNode:ParseTree):
        if tree is None:
            raise Exception("tree cannot be null")
        if pattern is None:
            raise Exception("pattern cannot be null")
        if labels is None:
            raise Exception("labels cannot be null")
        self.tree = tree
        self.pattern = pattern
        self.labels = labels
        self.mismatchedNode = mismatchedNode

    #
    # Get the last node associated with a specific {@code label}.
    #
    # <p>For example, for pattern {@code <id:ID>}, {@code get("id")} returns the
    # node matched for that {@code ID}. If more than one node
    # matched the specified label, only the last is returned. If there is
    # no node associated with the label, this returns {@code null}.</p>
    #
    # <p>Pattern tags like {@code <ID>} and {@code <expr>} without labels are

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Check the tree is not None before matching: if tree is not None: m = matcher.match(tree, pattern).
  2. For optional subrules, use a pattern that tolerates absence or check ctx.subrule_ctx is not None first.
  3. If you construct ParseTreeMatch by hand, validate all three required arguments (tree, pattern, labels).

Example fix

# before
m = matcher.match(ctx.expr(), pattern)  # expr() is None when the optional rule did not match

# after
expr = ctx.expr()
m = matcher.match(expr, pattern) if expr is not None else None
Defensive patterns

Strategy: type-guard

Validate before calling

if tree is None:
    raise ValueError('cannot pattern-match a None tree (optional subrule did not participate in the parse)')
result = matcher.match(tree, pattern)

Type guard

def matchable(tree):
    return tree is not None and hasattr(tree, 'accept')

Prevention

When it happens

Trigger: Calling matcher.match(None, pattern) or ParseTreeMatch(None, pattern, labels, None); also constructing ParseTreeMatch directly with a None tree.

Common situations: Walking code that grabs ctx.child(i) or a labelled subtree that can be None (optional subrule not matched) and feeds it straight into pattern matching; refactoring that drops the tree variable.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/43f1a0a110367b28. Report an issue: GitHub.