stanfordnlp/CoreNLP · error · IllegalArgumentException
Expected CoreLabel's to have after() text
Error message
Expected CoreLabel's to have after() text
What it means
To reproduce original spacing, spanString() reads CoreLabel.after() (the whitespace/characters following each word, BeforeAnnotation). If after() is null the reconstruction is ambiguous, so the library throws IllegalArgumentException for the first leaf lacking it.
Solutions
- Populate after() on each leaf, e.g. ((CoreLabel) leaf.label()).setAfter(" ") (or the actual trailing text) before spanString()
- Use CoreNLP's tokenizer (PTBTokenizer) which sets AfterAnnotation automatically, then build trees from its tokens
- Wrap spanString() in a null/after check and fall back to joining words with single spaces
Example fix
// before
String s = tree.spanString(); // throws when after()==null
// after
for (Tree leaf : tree.getLeaves()) { CoreLabel cl = (CoreLabel) leaf.label(); if (cl.after() == null) cl.setAfter(" "); }
String s = tree.spanString(); Defensive patterns
Strategy: validation
Validate before calling
for (Tree leaf : tree.getLeaves()) { CoreLabel cl = (CoreLabel) leaf.label(); if (cl.after() == null) cl.setAfter(" "); } Type guard
boolean leavesHaveAfter(Tree t) { return t.getLeaves().stream().allMatch(l -> ((CoreLabel) l.label()).after() != null); } Try / catch
try { return tree.spanString(); } catch (IllegalArgumentException e) { fillMissingAfter(tree); return tree.spanString(); } Prevention
- Prefer PTBTokenizer-produced tokens that carry AfterAnnotation
- Default after() to a single space when building labels manually
- Check after() before calling surface-text reconstruction
When it happens
Trigger: Calling spanString() on a tree whose leaf CoreLabels have word() set but never had the AfterAnnotation populated (e.g. labels built manually without whitespace info, or tokenizers that do not record trailing whitespace).
Common situations: Manually constructed CoreLabels in tests/pipelines where only word and tag were set; importing trees from other toolkits that don't track after-text; running spanString() on trees not produced by CoreNLP tokenization.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Expected leaves to be CoreLabels
- Expected CoreLabel's to have text
- Expected CoreLabels in the trees
- CORE: CoreLabel.initFromStrings: Can't handle
- CORE: CoreLabel.initFromStrings: Bad type for…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/29e4d10c5a4114fb.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/Tree.java:1023
return sw.toString();
}
/**
* Return String of leaves spanned by this tree assuming they are CoreLabel's
* Throws an IllegalArgumentException if the leaves are not CoreLabels that contain
* text info as in the typical use case of a Tree generated by a pipeline
*
* @return The text of the span of this Tree
*/
public String spanString() {
// check this Tree supports this method by having properly populated CoreLabel's
List<Tree> leaves = this.getLeaves();
if (!(leaves.get(0).label() instanceof CoreLabel)) {
throw new IllegalArgumentException("Expected leaves to be CoreLabels");
} else if (((CoreLabel) leaves.get(0).label()).word() == null) {
throw new IllegalArgumentException("Expected CoreLabel's to have text");
} else if (((CoreLabel) leaves.get(0).label()).after() == null) {
throw new IllegalArgumentException("Expected CoreLabel's to have after() text");
}
List<CoreLabel> coreLabels = this.getLeaves().stream().map(l -> ((CoreLabel) l.label())).collect(Collectors.toList());
// reconstruct original String from CoreLabel fields
String spanString = coreLabels.subList(0, Math.max(0, coreLabels.size()-1)).stream().map(
cl -> cl.word()+cl.after()).collect(Collectors.joining(""));
// don't add the after of the last word
spanString += coreLabels.get(coreLabels.size()-1).word();
return spanString;
}
/**
* Print the tree as done in Penn Treebank merged files.
* The formatting should be exactly the same, but we don't print the
* trailing whitespace found in Penn Treebank trees.
* The tree is printed to {@code System.out}. The basic deviation
* from a bracketed indented tree is to in general
* collapse the printing of adjacent preterminals onto one line ofView on GitHub (pinned to 1b7edd19c4)