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

  1. Populate after() on each leaf, e.g. ((CoreLabel) leaf.label()).setAfter(" ") (or the actual trailing text) before spanString()
  2. Use CoreNLP's tokenizer (PTBTokenizer) which sets AfterAnnotation automatically, then build trees from its tokens
  3. 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

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


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 of

View on GitHub (pinned to 1b7edd19c4)