{"record":{"id":"42c408a38efc2b8f","repo":"stanfordnlp/CoreNLP","slug":"error-no-such-thing-as-zeroth-child","errorCode":null,"errorMessage":"Error -- no such thing as zeroth child!","messagePattern":"Error -- no such thing as zeroth child!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/tregex/Relation.java","lineNumber":1368,"sourceCode":"    public int hashCode() {\n      int result = super.hashCode();\n      result = 29 * result\n          + (immediatelyHeads != null ? immediatelyHeads.hashCode() : 0);\n      return result;\n    }\n  }\n\n\n  private static class IthChildOf extends Relation {\n\n    private static final long serialVersionUID = -1463126827537879633L;\n\n    private final int childNum;\n\n    IthChildOf(int i) {\n      super('>' + String.valueOf(i));\n      if (i == 0) {\n        throw new IllegalArgumentException(\n            \"Error -- no such thing as zeroth child!\");\n      } else {\n        childNum = i;\n      }\n    }\n\n    @Override\n    Iterator<Tree> searchNodeIterator(final Tree t,\n                                      final TregexMatcher matcher) {\n      return new SearchNodeIterator() {\n        @Override\n        void initialize() {\n          if (t != matcher.getRoot()) {\n            next = matcher.getParent(t);\n            if (childNum > 0\n                && (next.numChildren() < childNum || next\n                    .getChild(childNum - 1) != t)\n                || childNum < 0","sourceCodeStart":1350,"sourceCodeEnd":1386,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/Relation.java#L1350-L1386","documentation":"Tregex's IthChildOf relation (>i or >-i) selects the i-th child of a node, with 1-based indexing (negative for counting from the end). i == 0 has no meaning (there is no zeroth child), so the constructor throws IllegalArgumentException.","triggerScenarios":"A tregex pattern contains '>0' (e.g. \"NP>0\"), so the parser constructs IthChildOf(0) and the constructor throws.","commonSituations":"Zero-based habits from array indexing leak into hand-written tregex queries; generated queries with loop counters starting at 0; users misremembering whether >1 is the first child.","solutions":["Use >1 for the first child (or >-1 for the last)","Adjust programmatic index generation to be 1-based","Validate user-supplied child indices != 0 before compiling the pattern"],"exampleFix":"// before\nString pattern = \"S >\" + childIdx; // childIdx == 0\n// after\nString pattern = \"S >\" + (childIdx + 1); // first child is >1","handlingStrategy":"validation","validationCode":"if (i == 0) throw new IllegalArgumentException(\"child index must be nonzero (1-based), got 0\");","typeGuard":"boolean validChildIndex(int i) { return i != 0; }","tryCatchPattern":"try { TregexPattern.compile(pattern); } catch (IllegalArgumentException e) { /* report bad >i index */ }","preventionTips":["First child is >1, last is >-1; 0 is always invalid","Sanitize user-supplied indices before building patterns","Add compile() smoke tests for generated queries"],"tags":["tregex","pattern-parsing","indexing"],"backgroundTag":"value-out-of-range","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}