stanfordnlp/CoreNLP · error · java.lang.RuntimeException

ERROR: to use SUTime, sentences must have TextAnnotation…

Error message

ERROR: to use SUTime, sentences must have TextAnnotation set, or the individual tokens must have OriginalTextAnnotation or TextAnnotation set!

What it means

NumberSequenceClassifier.buildSentenceFromTokens constructs a synthetic sentence for SUTime from a token list; it needs the sentence's TextAnnotation, or per-token OriginalTextAnnotation/TextAnnotation, to rebuild the text. When neither is present, text is null and this RuntimeException is thrown.

Solutions

  1. Ensure each token has TextAnnotation (coremap.get(CoreAnnotations.TextAnnotation.class)) set before invoking the classifier.
  2. Run the tokenize/ssa annotators upstream so text fields are populated rather than building CoreMaps manually.
  3. If you normalize tokens, also set OriginalTextAnnotation on each token.
  4. Set TextAnnotation on the containing sentence CoreMap.

Example fix

// before
CoreLabel tok = new CoreLabel();
tok.set(CoreAnnotations.ValueAnnotation.class, "five");
// after
CoreLabel tok = new CoreLabel();
tok.set(CoreAnnotations.TextAnnotation.class, "five");
Defensive patterns

Strategy: type-guard

Validate before calling

boolean sutimeReady(List<CoreLabel> tokens) {
  return tokens.stream().allMatch(t ->
    t.get(CoreAnnotations.TextAnnotation.class) != null ||
    t.get(CoreAnnotations.OriginalTextAnnotation.class) != null);
}

Type guard

static boolean hasTokenText(CoreLabel t) {
  return t.get(CoreAnnotations.TextAnnotation.class) != null
      || t.get(CoreAnnotations.OriginalTextAnnotation.class) != null;
}

Try / catch

try {
  sutime.classify(tokens);
} catch (RuntimeException e) {
  if (e.getMessage().contains("TextAnnotation")) {
    log.warning("Tokens lack text annotations; run tokenizer/ssa first");
  }
}

Prevention

When it happens

Trigger: Calling SUTime/NumberSequenceClassifier classification on CoreMaps that were created programmatically without TextAnnotation on the sentence and without TextAnnotation or OriginalTextAnnotation on each token — e.g. custom annotation code that sets only word()/value().

Common situations: Piping tokens from a custom reader/annotator into SUTime, calling SUTime directly on tokens built by hand, or an annotator order where tokens lost their text fields (e.g. after normalization that only sets normalized fields).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/636ea6278d1e1b46. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/ie/regexp/NumberSequenceClassifier.java:277

      Integer characterOffsetStart,
      Integer characterOffsetEnd) {

    //
    // Recover the sentence text:
    // a) try to get it from TextAnnotation
    // b) if not present, build it from the OriginalTextAnnotation of each token
    // c) if not present, build it from the TextAnnotation of each token
    //
    boolean adjustCharacterOffsets = false;
    // try to recover the text from the original tokens
    String text = buildText(tokens, CoreAnnotations.OriginalTextAnnotation.class);
    if(text == null){
      text = buildText(tokens, CoreAnnotations.TextAnnotation.class);
      // character offset will point to the original tokens
      //   so we need to align them to the text built from normalized tokens
      adjustCharacterOffsets = true;
      if(text == null){
        throw new RuntimeException("ERROR: to use SUTime, sentences must have TextAnnotation set, or the individual tokens must have OriginalTextAnnotation or TextAnnotation set!");
      }
    }

    // make sure token character offsets are aligned with text
    List<CoreLabel> tokenSequence = copyTokens(tokens, adjustCharacterOffsets, false);

    Annotation newSentence = new Annotation(text);
    newSentence.set(CoreAnnotations.TokensAnnotation.class, tokenSequence);
    if (! adjustCharacterOffsets &&
        characterOffsetStart != null &&
        characterOffsetEnd != null){
      newSentence.set(CoreAnnotations.CharacterOffsetBeginAnnotation.class, characterOffsetStart);
      newSentence.set(CoreAnnotations.CharacterOffsetEndAnnotation.class, characterOffsetEnd);
    } else {
      int tokenCharStart = tokenSequence.get(0).get(CoreAnnotations.CharacterOffsetBeginAnnotation.class);
      int tokenCharEnd = tokenSequence.get(tokenSequence.size() - 1).get(CoreAnnotations.CharacterOffsetEndAnnotation.class);
      newSentence.set(CoreAnnotations.CharacterOffsetBeginAnnotation.class, tokenCharStart);
      newSentence.set(CoreAnnotations.CharacterOffsetEndAnnotation.class, tokenCharEnd);

View on GitHub (pinned to 1b7edd19c4)