stanfordnlp/CoreNLP · error · IllegalArgumentException
Word " + wordCount + " (\"" +…
Error message
Word " + wordCount + " (\"" + token.get(CoreAnnotations.TextAnnotation.class) + "\") has a blank answer
What it means
During CRF training, every training token must carry a non-null, non-empty AnswerAnnotation label, because the classIndex of possible labels is built from these answers. A token without a label makes the training data ill-formed, so an IllegalArgumentException naming the word index and text is thrown.
Solutions
- Set an answer label on every training token: token.set(CoreAnnotations.AnswerAnnotation.class, label) before training.
- Fix the input reader so the gold-label column maps to the 'answer' field (check the column mapping in your training properties, e.g. map=0=word,1=answer).
- Pre-validate the training corpus: scan all docs and fail fast on any token with a blank answer, then repair the source data.
Example fix
// before
for (CoreLabel tok : doc) { docOut.add(tok); } // answer never set
// after
for (CoreLabel tok : doc) {
if (tok.get(CoreAnnotations.AnswerAnnotation.class) == null)
tok.set(CoreAnnotations.AnswerAnnotation.class, goldLabel);
docOut.add(tok);
} Defensive patterns
Strategy: validation
Validate before calling
for (List<IN> doc : trainingDocs) {
int i = 0;
for (IN tok : doc) {
String ans = tok.get(CoreAnnotations.AnswerAnnotation.class);
if (ans == null || ans.isEmpty())
throw new IllegalStateException("Token " + i + " (" + tok.get(CoreAnnotations.TextAnnotation.class) + ") has blank answer");
i++;
}
} Try / catch
try {
classifier.train(trainingDocs);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("has a blank answer")) {
log.severe("Training data has unlabeled tokens: " + e.getMessage());
}
throw e;
} Prevention
- Always call setAnswer()/set(CoreAnnotations.AnswerAnnotation.class, ...) when building training docs programmatically.
- Verify the reader's column mapping puts the gold label in the answer field.
- Lint the training corpus for null/empty answers before training.
When it happens
Trigger: Calling train()/trainSeqModel (via the CRFClassifier constructor path shown) on a List<IN> document where any CoreLabel lacks CoreAnnotations.AnswerAnnotation (answer field), or has answer set to "".
Common situations: Building training documents programmatically and forgetting to setAnswer(); reading CoNLL/TSV files where some rows have no gold label column; filtering that drops labels; sentence boundaries misparsed so unlabeled tokens slip in.
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
- Unknown feature type " + feature
- Incompatible CRFClassifier: weight length mismatch for…
- Incompatible CRFClassifier: pad does not match
- Incompatible CRFClassifier: windowSize does not match
- Incompatible CRFClassifier: labelIndices length does not…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/8c74d91b2e4127cd.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/ie/crf/CRFClassifier.java:732
int wordCount = 0;
if (flags.labelDictionaryCutoff > 0) {
this.labelDictionary = new LabelDictionary();
}
for (List<IN> doc : ob) {
if (flags.useReverse) {
Collections.reverse(doc);
}
// create the full set of labels in classIndex
// note: update to use addAll later
for (IN token : doc) {
wordCount++;
String ans = token.get(CoreAnnotations.AnswerAnnotation.class);
if (ans == null || ans.isEmpty()) {
throw new IllegalArgumentException("Word " + wordCount + " (\"" + token.get(CoreAnnotations.TextAnnotation.class) + "\") has a blank answer");
}
classIndex.add(ans);
if (labelDictionary != null) {
String observation = token.get(CoreAnnotations.TextAnnotation.class);
labelDictionary.increment(observation, ans);
}
}
for (int j = 0, docSize = doc.size(); j < docSize; j++) {
CRFDatum<Collection<String>, CRFLabel> d = makeDatum(doc, j, featureFactories);
labelIndex.add(d.label());
List<Collection<String>> features = d.asFeatures();
for (int k = 0, fSize = features.size(); k < fSize; k++) {
Collection<String> cliqueFeatures = features.get(k);
if (k < 2 && flags.removeBackgroundSingletonFeatures) {
String ans = doc.get(j).get(CoreAnnotations.AnswerAnnotation.class);
boolean background = ans.equals(flags.backgroundSymbol);View on GitHub (pinned to 1b7edd19c4)