stanfordnlp/CoreNLP · error · java.lang.RuntimeException

Unexpected class while adding word () in phrase

Error message

Unexpected class  while adding word () in phrase 

What it means

PhraseTable's internal trie is built from nested Maps whose leaves are Lists of Phrase objects or nested Maps. addPhrase traverses the trie and throws when a node it must descend into is none of Map, List, or Phrase — a corrupted or unexpected trie node type.

Solutions

  1. Use only the public addPhrase API; never insert raw values into the internal tree structure
  2. Synchronize phrase-table population or build it single-threaded before use
  3. Inspect the trie node at the failing word index to find what wrote the unexpected object

Example fix

// before (custom insertion)
((Map) trieNode).put(word, "someString");
// after
table.addPhrase(wordList, phraseText, tag, data); // let PhraseTable manage node types
Defensive patterns

Strategy: try-catch

Validate before calling

Object node = null; // only inspect via public API; do not write into the tree directly
if (!tableClassNodeTypesOk) rebuildTable();

Type guard

static boolean validTrieNode(Object n) { return n instanceof Map || n instanceof List || n instanceof Phrase; }

Try / catch

try { table.addPhrase(wordList, text, tag, data); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unexpected class")) { rebuildPhraseTableFromSource(); } else throw e; }

Prevention

When it happens

Trigger: The trie node for a word was previously set to an unexpected object type (e.g. a String or Phrase where a container was required) and a longer phrase sharing that prefix is added afterwards.

Common situations: Concurrent/unsynchronized mutation of the trie from multiple threads (the Map overload is not synchronized) corrupting node types; custom code writing directly into the internal tree map.

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


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

Appendix: source

Thrown at src/edu/stanford/nlp/ling/tokensregex/PhraseTable.java:355

  private synchronized void addPhrase(Map<String,Object> tree, Phrase phrase, int wordIndex)
  {
    String word = (phrase.wordList.size() <= wordIndex)? PHRASE_END:phrase.wordList.getWord(wordIndex);
    Object node = tree.get(word);
    if (node == null) {
      tree.put(word, phrase);
    } else if (node instanceof Phrase) {
      // create list with this phrase and other and put it here
      List<Object> list = new ArrayList<>(2);
      list.add(phrase);
      list.add(node);
      tree.put(word, list);
    } else if (node instanceof Map) {
      addPhrase((Map<String,Object>) node, phrase, wordIndex+1);
    } else if (node instanceof List) {
      ((List) node).add(phrase);
    } else {
      throw new RuntimeException("Unexpected class " + node.getClass() + " while adding word "
              + wordIndex + "(" + word + ") in phrase " + phrase.getText());
    }
  }

  private synchronized boolean addPhrase(Map<String,Object> tree,
                                         String phraseText, String tag, WordList wordList, Object phraseData, int wordIndex)
  {
    // Find place to insert this item
    boolean phraseAdded = false;  // True if this phrase was successfully added to the phrase table
    boolean newPhraseAdded = false;    // True if the phrase was a new phrase
    boolean oldPhraseNewFormAdded = false;      // True if the phrase already exists, and this was new form added to old phrase
    for (int i = wordIndex; i < wordList.size(); i++) {
      String word = Interner.globalIntern(wordList.getWord(i));
      Object node = tree.get(word);
      if (node == null) {
        // insert here
        Phrase phrase = new Phrase(wordList, phraseText, tag, phraseData);
        tree.put(word, phrase);

View on GitHub (pinned to 1b7edd19c4)