stanfordnlp/CoreNLP · error · RuntimeException

unexpected match type

Error message

unexpected match type

What it means

TimexTreeAnnotator.annotate switches over the match type found when locating the TIMEX3 expression in a parse tree; the default branch throws RuntimeException 'unexpected match type' because only the handled match types are implemented. It is an exhaustiveness guard for future/unknown match types.

Solutions

  1. Inspect which match type is produced for your corpus and add a case handling it (the comment invites adding cases)
  2. Pre-filter documents whose TIMEX3 matches are not the supported types
  3. Catch RuntimeException per-document and record skipped Timexes instead of aborting the run
  4. Update the Stanford CoreNLP version, as match handling may have improved

Example fix

// before
default:
  throw new RuntimeException("unexpected match type");
// after
default:
  log.warning("Skipping Timex with unhandled match type: " + matchType);
  subtree = null;
  break;
Defensive patterns

Strategy: try-catch

Validate before calling

if (unsupportedMatchType(matchType)) { skipTimex(); }

Try / catch

try { annotator.annotate(coreMap); } catch (RuntimeException e) { log.warn("skipped document: " + e.getMessage()); }

Prevention

When it happens

Trigger: Running TimexTreeAnnotator (or its main) over a corpus where the Timex-to-tree matcher returns a MatchType the annotator has no case for, e.g. match types spanning multiple subtrees that were never implemented (the comment notes 'more cases could go here').

Common situations: Annotating TimeBank-style documents where some TIMEX3 expressions match discontinuous or multi-node regions not covered by the implemented cases.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/time/TimexTreeAnnotator.java:70

          // select the smallest enclosing tree
        case SmallestEnclosing:
          possibleMatches = Iterables.filter(tree, tree1 -> {
            int treeBegin = beginOffset(tree, tokens);
            int treeEnd = endOffset(tree, tokens);
            return treeBegin <= timexBegin && timexEnd <= treeEnd;
          });
          List<Tree> sortedMatches = CollectionUtils.toList(possibleMatches);
          Collections.sort(sortedMatches, (tree1, tree2) -> {
            Integer width1 = endOffset(tree1, tokens) - beginOffset(tree1, tokens);
            Integer width2 = endOffset(tree2, tokens) - endOffset(tree2, tokens);
            return width1.compareTo(width2);
          });
          subtree = sortedMatches.get(0);
          break;
          
          // more cases could go here if they're added
        default:
          throw new RuntimeException("unexpected match type");
        }
  	
        // add the subtree to the time annotation
        if (subtree != null) {
          timexAnn.set(TreeCoreAnnotations.TreeAnnotation.class, subtree);
        }
      }
    }
  }
  
  private static int beginOffset(Tree tree, List<CoreLabel> tokens) {
    CoreMap label = (CoreMap)tree.label();
    int beginToken = label.get(CoreAnnotations.BeginIndexAnnotation.class);
    return beginOffset(tokens.get(beginToken));
  }
  
  private static int endOffset(Tree tree, List<CoreLabel> tokens) {
    CoreMap label = (CoreMap)tree.label();

View on GitHub (pinned to 1b7edd19c4)