stanfordnlp/CoreNLP · error · IllegalArgumentException

We need at least 2 extractors for ExtractorMerger to make…

Error message

We need at least 2 extractors for ExtractorMerger to make sense.

What it means

The ExtractorMerger constructor validates its input: it exists solely to merge the output of multiple extractors, so an array with fewer than 2 extractors is meaningless and throws IllegalArgumentException. This is a fail-fast constructor argument check.

Solutions

  1. Only construct ExtractorMerger when you actually have two or more extractors to combine.
  2. Add a guard: if extractors.length == 1 use it directly instead of wrapping it in a merger.
  3. Fix the config/assembly code that produced fewer than 2 extractors (check for silently filtered-out entries).
  4. Null-check the array before the length check to convert a potential NPE into a clear error.

Example fix

// before
ExtractorMerger merger = new ExtractorMerger(extractors);
// after
Extractor extractor = extractors.length == 1 ? extractors[0] : new ExtractorMerger(extractors);
Defensive patterns

Strategy: validation

Validate before calling

if (extractors == null || extractors.length < 2) {
  throw new IllegalArgumentException("ExtractorMerger requires at least 2 extractors");
}

Type guard

boolean mergable(Extractor[] extractors) {
  return extractors != null && extractors.length >= 2;
}

Try / catch

try {
  extractor = new ExtractorMerger(extractors);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("at least 2 extractors")) {
    extractor = extractors.length == 1 ? extractors[0] : null;
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling new ExtractorMerger(new Extractor[0]) or new ExtractorMerger(new Extractor[]{oneExtractor}) — i.e. constructing the merger with an empty or single-element extractor array (also a null array, via NPE on .length).

Common situations: Building an extractor list from config that filtered down to one (or zero) extractors; accidental array slicing/concatenation bug; code that unconditionally wraps in ExtractorMerger even when only one extractor is enabled.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/ie/machinereading/ExtractorMerger.java:31

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.util.CoreMap;

/**
 * Simple extractor which combines several other Extractors.  Currently only works with RelationMentions.
 * Also note that this implementation uses Sets and will mangle the original order of RelationMentions.
 *
 * @author David McClosky
 */
public class ExtractorMerger implements Extractor {

  private static final long serialVersionUID = 1L;
  private static final Logger logger = Logger.getLogger(ExtractorMerger.class.getName());
  private Extractor[] extractors;

  public ExtractorMerger(Extractor[] extractors) {
    if (extractors.length < 2) {
      throw new IllegalArgumentException("We need at least 2 extractors for ExtractorMerger to make sense.");
    }
    this.extractors = extractors;
  }

  @Override
  public void annotate(Annotation dataset) {
    // TODO for now, we only merge RelationMentions
    logger.info("Extractor 0 annotating dataset.");
    extractors[0].annotate(dataset);

    // store all the RelationMentions per sentence
    List<Set<RelationMention>> allRelationMentions = new ArrayList<>();
    for (CoreMap sentence : dataset.get(CoreAnnotations.SentencesAnnotation.class)) {
      List<RelationMention> relationMentions = sentence.get(MachineReadingAnnotations.RelationMentionsAnnotation.class);
      Set<RelationMention> uniqueRelationMentions = new HashSet<>(relationMentions);
      allRelationMentions.add(uniqueRelationMentions);
    }

View on GitHub (pinned to 1b7edd19c4)