stanfordnlp/CoreNLP · error · RuntimeException

ERROR: Relation extraction requires full syntactic analysis!

Error message

ERROR: Relation extraction requires full syntactic analysis!

What it means

BasicRelationFeatureFactory.addFeatures needs the parse tree of the relation's sentence (TreeAnnotation) to compute syntactic features such as constituent paths between arguments. If the input CoreMap sentence was never annotated with a parse, it throws RuntimeException. Relation extraction requires the full preprocessing pipeline (POS + parsing) to have run before feature extraction.

Solutions

  1. Add the "parse" (or "parser") annotator to your StanfordCoreNLP pipeline before relation extraction.
  2. Verify each sentence CoreMap has a non-null TreeAnnotation before invoking addFeatures.
  3. If using pre-annotated input, ensure the producer ran syntactic analysis and that serialization preserves the tree.
  4. Replace CoreAnnotations.TreeAnnotation checks with a guard that logs and skips unparseable sentences if degraded features are acceptable.

Example fix

// before
props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner");
// after
props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner,parse");
Defensive patterns

Strategy: type-guard

Validate before calling

CoreMap sent = rel.getSentence();
if (sent == null || sent.get(TreeAnnotation.class) == null) {
  throw new IllegalStateException("Sentence lacks parse tree; add the 'parse' annotator before relation extraction.");
}

Type guard

boolean hasParse(RelationMention rel) {
  CoreMap sent = rel.getSentence();
  return sent != null && sent.get(TreeAnnotation.class) != null;
}

Try / catch

try {
  features = featureFactory.addFeatures(rel, ...);
} catch (RuntimeException e) {
  if (e.getMessage().contains("requires full syntactic analysis")) {
    log.severe("Pipeline missing parse annotator: " + e.getMessage());
    throw new IllegalArgumentException("Enable the 'parse' annotator in your StanfordCoreNLP pipeline", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling createDatum/addFeatures on a Relation whose sentence CoreMap lacks TreeAnnotation — i.e. the text was not run through a parser annotator (or the parse was dropped) before relation extraction.

Common situations: Building an Annotation pipeline with only tokenize/ssplit/ner and skipping 'parse'; passing sentences extracted from a custom reader that does not attach TreeAnnotation; serializing/deserializing annotations and losing the Tree; running on pre-annotated data produced by an older pipeline version.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/ie/machinereading/BasicRelationFeatureFactory.java:142

  /**
   * Creates all features for the datum corresponding to this relation mention
   * Note: this assumes binary relations where both arguments are EntityMention
   * @param features Stores all features
   * @param rel The mention
   * @param types Comma separated list of feature classes to use
   */
  public boolean addFeatures(Counter<String> features, RelationMention rel, List<String> types, Logger logger) {
    // sanity checks: must have two arguments, and each must be an entity mention
    if(rel.getArgs().size() != 2) return false;
    if(! (rel.getArg(0) instanceof EntityMention)) return false;
    if(! (rel.getArg(1) instanceof EntityMention)) return false;

    EntityMention arg0 = (EntityMention) rel.getArg(0);
    EntityMention arg1 = (EntityMention) rel.getArg(1);

    Tree tree = rel.getSentence().get(TreeAnnotation.class);
    if(tree == null){
      throw new RuntimeException("ERROR: Relation extraction requires full syntactic analysis!");
    }
    List<Tree> leaves = tree.getLeaves();
    List<CoreLabel> tokens = rel.getSentence().get(TokensAnnotation.class);

    // this assumes that both args are in the same sentence as the relation object
    // let's check for this to be safe
    CoreMap relSentence = rel.getSentence();
    CoreMap arg0Sentence = arg0.getSentence();
    CoreMap arg1Sentence = arg1.getSentence();
    if(arg0Sentence != relSentence){
      log.info("WARNING: Found relation with arg0 in a different sentence: " + rel);
      log.info("Relation sentence: " + relSentence.get(TextAnnotation.class));
      log.info("Arg0 sentence: " + arg0Sentence.get(TextAnnotation.class));
      return false;
    }
    if(arg1Sentence != relSentence){
      log.info("WARNING: Found relation with arg1 in a different sentence: " + rel);
      log.info("Relation sentence: " + relSentence.get(TextAnnotation.class));

View on GitHub (pinned to 1b7edd19c4)