stanfordnlp/CoreNLP · error · IllegalArgumentException

Unknown annotator

Error message

Unknown annotator: ${annotator}

What it means

ensurePrerequisiteAnnotators validates every annotator name in the requested list against the registry of named annotators (getNamedAnnotators()). If a name is not registered (case-insensitively), it throws IllegalArgumentException 'Unknown annotator'.

Solutions

  1. Fix the annotator name to a valid one (tokenize, ssplit, pos, lemma, ner, parse, depparse, coref, dcoref, natlog, sentiment, etc.).
  2. Register a custom annotator via props 'customAnnotatorClass.<name> = fqcn' so the name resolves.
  3. Call StanfordCoreNLP.getNamedAnnotators() (or print AvailableEditors/defaults) to list valid names for your version.
  4. Remove annotators made unavailable by a version upgrade and add their modern replacements.

Example fix

// before
props.setProperty("annotators", "tokenize, ssplit, tokenize");
// after
props.setProperty("annotators", "tokenize,ssplit,pos,lemma");
Defensive patterns

Strategy: validation

Validate before calling

Set<String> known = StanfordCoreNLP.getNamedAnnotators().keySet();
for (String a : props.getProperty("annotators").split(",\\s*")) {
  if (!known.contains(a.trim().toLowerCase())) {
    throw new IllegalArgumentException("Invalid annotator: " + a);
  }
}

Try / catch

try { pipeline = new StanfordCoreNLP(props); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unknown annotator")) { log.error("Check annotators property: {}", e.getMessage()); } throw e; }

Prevention

When it happens

Trigger: Setting props 'annotators' to a name not in the registry, e.g. misspellings ('tokenizer', 'sentencesplit'), custom annotators not registered via AnnotationsPipeline/customAnnotatorClass, or names removed in newer CoreNLP versions.

Common situations: Typo in StanfordCoreNLP.properties annotators line; copying config from a tutorial using an old annotator name; expecting a model-specific annotator without loading the right models jar.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/StanfordCoreNLP.java:492

   * pos. As a side effect, this function orders the annotators in the proper order.
   * Note that this is not guaranteed to return a valid set of annotators,
   * as properties passed to the annotators can change their requirements.
   *
   * @param annotators The annotators the user has requested.
   * @return A sanitized annotators string with all prerequisites met.
   */
  public static String ensurePrerequisiteAnnotators(String[] annotators, Properties props) {
    int posIndex = ArrayUtils.indexOf(annotators, Annotator.STANFORD_POS);
    int parseIndex = ArrayUtils.indexOf(annotators, Annotator.STANFORD_PARSE);
    boolean useParseForPos = ((parseIndex >= 0) && (posIndex < 0)); // Already doing the parsing, use the parsing for the pos tag

    // Get an unordered set of annotators
    Set<String> unorderedAnnotators = new LinkedHashSet<>();  // linked to preserve order
    Collections.addAll(unorderedAnnotators, annotators);
    for (String annotator : annotators) {
      // Add the annotator
      if (!getNamedAnnotators().containsKey(annotator.toLowerCase())) {
        throw new IllegalArgumentException("Unknown annotator: " + annotator);
      }

      // Add its transitive dependencies
      unorderedAnnotators.add(annotator.toLowerCase());
      if (!Annotator.DEFAULT_REQUIREMENTS.containsKey(annotator.toLowerCase())) {
        throw new IllegalArgumentException("Cannot infer requirements for annotator: " + annotator);
      }
      Queue<String> fringe = new LinkedList<>(Annotator.DEFAULT_REQUIREMENTS.get(annotator.toLowerCase()));
      int ticks = 0;
      while (!fringe.isEmpty()) {
        ticks += 1;
        if (ticks == 1000000) {
          throw new IllegalStateException("[INTERNAL ERROR] Annotators have a circular dependency.");
        }
        String prereq = fringe.poll();
        unorderedAnnotators.add(prereq);
        fringe.addAll(Annotator.DEFAULT_REQUIREMENTS.get(prereq.toLowerCase()));
      }

View on GitHub (pinned to 1b7edd19c4)