stanfordnlp/CoreNLP · error · java.lang.RuntimeException
Unexpected class in list while looking up word () in…
Error message
Unexpected class in list while looking up word () in phrase
What it means
While walking the trie during lookup, a List node must contain only Phrase and (at most one) Map elements. Encountering any other object type inside the list throws this RuntimeException, indicating the PhraseTable's internal structure was corrupted or tampered with.
Solutions
- Rebuild the PhraseTable single-threaded (or under one lock) from the source phrase list.
- Stop any code that touches the table's internal Map/List objects directly.
- Use the immutable pattern: build once, then only call lookup/read methods from other threads.
- Upgrade CoreNLP and report with a reproducer if corruption occurs without concurrent writes.
Example fix
// before List<Object> list = (List<Object>) getRootTree().get(word); list.add(myCustomObject); // poisons the table // after table.addPhrases(Arrays.asList(myPhraseStrings)); // only public API
Defensive patterns
Strategy: validation
Validate before calling
// only public API may touch the table; assert no reflective access table.addPhrases(phrases); // then treat as immutable
Type guard
boolean isValidNode(Object o) { return o == null || o instanceof Phrase || o instanceof Map || o instanceof List; } Try / catch
try { return table.lookup(wordList); } catch (RuntimeException e) { if (e.getMessage().contains("Unexpected class")) { table = rebuild(phrases); return table.lookup(wordList); } throw e; } Prevention
- Use only addPhrase/addPhrases/lookup public methods.
- Share the table across threads only after building completes.
- Avoid serializing/deserializing internal structures across versions.
When it happens
Trigger: lookup(WordList) reaching a lookupList that holds an object that is neither Phrase nor Map - caused by concurrent addPhrase races or external mutation of the internal lists.
Common situations: Multi-threaded table construction; reflection/serialization experiments on the table; mixing objects from different PhraseTable instances.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Unexpected class while looking up
- Invalid node pattern class: for variable
- Invalid node pattern variable class: for variable
- Invalid sequence pattern variable class:
- Unexpected class while adding word () in phrase
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/ce56a199e2d368a5.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/ling/tokensregex/PhraseTable.java:571
for (Object obj:lookupList) {
if (obj instanceof Phrase) {
// check rest of the phrase matches
Phrase phrase = (Phrase) obj;
int matchedTokenEnd = checkWordListMatch(
phrase, wordList, 0, wordList.size(), i, true);
if (matchedTokenEnd >= 0) {
return phrase;
}
} else if (obj instanceof Map) {
if (nMaps == 1) {
throw new RuntimeException("More than one map in list while looking up word "
+ i + "(" + word + ") in phrase " + wordList.toString());
}
tree = (Map<String, Object>) obj;
nMaps++;
} else {
throw new RuntimeException("Unexpected class in list " + obj.getClass() + " while looking up word "
+ i + "(" + word + ") in phrase " + wordList.toString());
}
}
if (nMaps == 0) {
return null;
}
} else {
throw new RuntimeException("Unexpected class in list " + node.getClass() + " while looking up word "
+ i + "(" + word + ") in phrase " + wordList.toString());
}
}
Phrase phrase = (Phrase) tree.get(PHRASE_END);
if (phrase != null) {
int matchedTokenEnd = checkWordListMatch(
phrase, wordList, 0, wordList.size(), wordList.size(), true);
return (matchedTokenEnd >= 0)? phrase:null;
} else {
return null;View on GitHub (pinned to 1b7edd19c4)