{"record":{"id":"7e7fba89fba449f0","repo":"antlr/antlr4","slug":"tree-cannot-be-null-7e7fba","errorCode":null,"errorMessage":"tree cannot be null","messagePattern":"tree cannot be null","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs","lineNumber":395,"sourceCode":"        /// </summary>\n        /// <returns>\n        /// the first node encountered in\n        /// <paramref name=\"tree\"/>\n        /// which does not match\n        /// a corresponding node in\n        /// <paramref name=\"patternTree\"/>\n        /// , or\n        /// <see langword=\"null\"/>\n        /// if the match\n        /// was successful. The specific node returned depends on the matching\n        /// algorithm used by the implementation, and may be overridden.\n        /// </returns>\n        [return: Nullable]\n        protected internal virtual IParseTree MatchImpl(IParseTree tree, IParseTree patternTree, MultiMap<string, IParseTree> labels)\n        {\n            if (tree == null)\n            {\n                throw new ArgumentException(\"tree cannot be null\");\n            }\n            if (patternTree == null)\n            {\n                throw new ArgumentException(\"patternTree cannot be null\");\n            }\n            // x and <ID>, x and y, or x and x; or could be mismatched types\n            if (tree is ITerminalNode && patternTree is ITerminalNode)\n            {\n                ITerminalNode t1 = (ITerminalNode)tree;\n                ITerminalNode t2 = (ITerminalNode)patternTree;\n                IParseTree mismatchedNode = null;\n                // both are tokens and they have same type\n                if (t1.Symbol.Type == t2.Symbol.Type)\n                {\n                    if (t2.Symbol is TokenTagToken)\n                    {\n                        // x and <ID>\n                        TokenTagToken tokenTagToken = (TokenTagToken)t2.Symbol;","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs#L377-L413","documentation":"ParseTreePatternMatcher.MatchImpl rejects a null tree argument. MatchImpl is the protected recursion engine behind ParseTreePattern.Match(); every level of the recursion passes subtree children in, and a null there indicates a structural bug (a child accessor returned null) or a custom override calling it with null. The public API never passes null from a real parse tree.","triggerScenarios":"Overriding or calling MatchImpl(null, patternTree, labels) directly; a custom IParseTree implementation whose GetChild() returns null for valid indexes, which the recursion then feeds into MatchImpl.","commonSituations":"Subclassing the pattern matcher to customize matching; wrapping/altering parse trees with custom node types that violate the IParseTree contract; porting code from an older runtime where null children were tolerated.","solutions":["Do not call MatchImpl yourself; use tree.Pattern(p).Match() / p.Match(tree).","In overrides, guard children before recursing: skip null children or treat them as mismatches instead of passing them down.","Fix custom IParseTree implementations so GetChild(i) never returns null for i < ChildCount."],"exampleFix":"// before\nprotected override IParseTree MatchImpl(IParseTree tree, IParseTree patternTree, MultiMap<string, IParseTree> labels)\n{\n    return base.MatchImpl(GetChildOrNull(tree, 0), patternTree, labels);\n}\n\n// after\nvar child = GetChildOrNull(tree, 0);\nreturn child == null ? tree /* mismatch */ : base.MatchImpl(child, patternTree, labels);","handlingStrategy":"validation","validationCode":"// In overrides, guard children before recursing\nfor (int i = 0; i < tree.ChildCount; i++)\n{\n    var child = tree.GetChild(i);\n    if (child == null) continue; // treat as mismatch instead of throwing\n    var r = MatchImpl(child, patternTree.GetChild(i), labels);\n}","typeGuard":"static bool HasTree(IParseTree t) => t != null;","tryCatchPattern":null,"preventionTips":["Use the public Match API rather than calling MatchImpl directly.","Ensure custom IParseTree implementations never return null from GetChild for valid indexes."],"tags":["antlr","csharp","pattern-matcher","null-check","match"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}