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
- Fix the annotator name to a valid one (tokenize, ssplit, pos, lemma, ner, parse, depparse, coref, dcoref, natlog, sentiment, etc.).
- Register a custom annotator via props 'customAnnotatorClass.<name> = fqcn' so the name resolves.
- Call StanfordCoreNLP.getNamedAnnotators() (or print AvailableEditors/defaults) to list valid names for your version.
- 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
- Keep a whitelist of valid annotator names for your CoreNLP version and validate config at startup.
- Register custom annotators with customAnnotatorClass.<name> before referencing them.
- Re-validate annotator names after any CoreNLP version upgrade.
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
- Unknown parser type: " + parserType + " (currently…
- Cannot infer requirements for annotator
- Unsatisfiable annotator list
- Unknown LogPriorType:
- unsupported language
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)