antlr/antlr4 · error · Exception
pattern cannot be null
Error message
pattern cannot be null
What it means
Companion check in the same constructor: the ParseTreePattern handed to ParseTreeMatch must not be None. The pattern object is normally obtained from compiler.compile(patternText, patternRuleIndex); if that result (or a hand-built pattern) is None and is passed on, this exception is raised.
Source
Thrown at runtime/Python3/src/antlr4/tree/ParseTreeMatch.py:37
# 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
# considered to be labeled with {@code ID} and {@code expr}, respectively.</p>
#View on GitHub (pinned to 7d5770395b)
Solutions
- Compile the pattern once and assert it is not None before use: pattern = matcher.compile('<ID>', parser.ruleNames.index('expr')).
- Use dict indexing or setdefault so a missing cached pattern raises at the lookup, not deep inside match().
- Do not swallow exceptions from compile(); let them propagate or substitute a known-good pattern.
Example fix
# before
pattern = pattern_cache.get(rule_name) # None on first use
m = matcher.match(tree, pattern) # -> 'pattern cannot be null'
# after
if rule_name not in pattern_cache:
pattern_cache[rule_name] = matcher.compile(rule_pattern_text, parser.ruleNames.index(rule_name))
m = matcher.match(tree, pattern_cache[rule_name]) Defensive patterns
Strategy: validation
Validate before calling
if pattern is None:
pattern = matcher.compile(pattern_text, parser.ruleNames.index(rule_name))
assert pattern is not None
result = matcher.match(tree, pattern) Type guard
def compiled_pattern(matcher, cache, name, text, parser):
if name not in cache:
cache[name] = matcher.compile(text, parser.ruleNames.index(name))
return cache[name] Prevention
- Cache compiled patterns with explicit insertion, not dict.get that yields None
- Never swallow exceptions from ParseTreePatternMatcher.compile
- Compile patterns once at startup so a bad pattern fails fast, not mid-parse
When it happens
Trigger: matcher.match(tree, None), or reusing a pattern variable that failed to be created (e.g. an exception during compile was swallowed and left it None).
Common situations: Storing compiled patterns in a dict that may not contain the key (pattern = cache.get(name) returning None); swallowing compile exceptions with a bare except and continuing with a None pattern.
Related errors
- tree cannot be null
- delegates
- replace: range invalid: {}..{}(size={})
- replace op boundaries of {} overlap with previous {}
- insert op {} within boundaries of previous {}
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/7576ae85f77516b1.
Report an issue: GitHub.