stanfordnlp/CoreNLP · warning
: Unknown field: cannot find suitable annotation class
Error message
${name}: Unknown field: ${field} cannot find suitable annotation class What it means
TokensRegexNERAnnotator lets rules map fields to CoreNLP annotation classes. When a field name in a rule header cannot be resolved to any Annotation key class (via EnvLookup), the annotator logs this warning and simply omits that field. Rules still load, but the intended field will never be populated.
Solutions
- Check the field name spelling in the rules file header against CoreNLP's CoreAnnotations classes
- Use the Classname: suffix (e.g. myfield:edu.stanford.nlp.ling.CoreAnnotations$NormalizedNamedEntityTag) so the class can be found
- Remove fields you don't actually need from the rule header
- Verify the CoreNLP version supports the field you reference
Example fix
// before (rules file header)
tokens = { word: /Barack/ }
PosTag: NN
// after
tokens = { word: /Barack/ }
PartOfSpeech: NN Defensive patterns
Strategy: validation
Validate before calling
Set<String> known = Set.of("text","word","lemma","pos","ner","normalized","partOfSpeech");
for (String field : headerFields) {
if (!known.contains(field) && !field.contains(":"))
throw new IllegalArgumentException("Unknown rule field: " + field);
} Prevention
- Cross-check rule header fields against CoreAnnotations class names
- Use the Field:classname syntax for custom keys
- Keep a lint step that loads rule files and fails on unknown fields
- Pin the CoreNLP version so field names match documentation
When it happens
Trigger: Defining a TokensRegex rules file with a header field whose name (or explicit classname after ':') does not correspond to any CoreNLP annotation class, e.g. a typo like 'PartOfSpeach' or a custom name without a registered class.
Common situations: Typo'd field names in tokensregex rules; custom annotation keys used in rules without registering/looking up the class name; copy-pasting rule headers between CoreNLP versions where a field was renamed.
Related errors
- Number in types column for
- : Entry has multiple types for : . Taking type to be
- : Replacing duplicate entry (higher priority): old= , new=
- : Ignoring duplicate entry: , old type = , new type =
- : Entry doesn't have overwriteable types , but entry type…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/b0aa0e9f709aa21f.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/pipeline/TokensRegexNERAnnotator.java:292
} else {
headerFields = COMMA_DELIMITERS_PATTERN.split(headerProp);
// Take header fields and remove known headers to get annotation field names
List<String> fieldNames = new ArrayList<>();
List<Class> fieldClasses = new ArrayList<>();
for (String field : headerFields) {
if ( ! predefinedHeaderFields.contains(field)) {
Class fieldClass = EnvLookup.lookupAnnotationKeyWithClassname(null, field);
if (fieldClass == null) {
// check our properties
String classname = properties.getProperty(prefix + "mapping.field." + field);
fieldClass = EnvLookup.lookupAnnotationKeyWithClassname(null, classname);
}
if (fieldClass != null) {
fieldNames.add(field);
fieldClasses.add(fieldClass);
} else {
logger.warn(name + ": Unknown field: " + field + " cannot find suitable annotation class");
}
}
}
annotationFieldnames = new String[fieldNames.size()];
fieldNames.toArray(annotationFieldnames);
annotationFields = fieldClasses;
}
String noDefaultOverwriteLabelsProp = properties.getProperty(prefix + "noDefaultOverwriteLabels", "CITY");
this.noDefaultOverwriteLabels = Collections.unmodifiableSet(CollectionUtils.asSet(COMMA_DELIMITERS_PATTERN.split(noDefaultOverwriteLabelsProp)));
this.ignoreCase = PropertiesUtils.getBool(properties, prefix + "ignorecase", false);
this.verbose = PropertiesUtils.getBool(properties, prefix + "verbose", false);
if ( ! StringUtils.isNullOrEmpty(validPosRegex)) {
validPosPattern = Pattern.compile(validPosRegex);
} else {
validPosPattern = null;View on GitHub (pinned to 1b7edd19c4)