stanfordnlp/CoreNLP · error · IllegalArgumentException

There is already a relation named

Error message

There is already a relation named <relation>!

What it means

Every GrammaticalRelation registers itself in a global per-language stringsToRelations map at construction time. If another relation with the same name already exists in that map and neither is a 'fake' relation created fromString, the constructor throws this IllegalArgumentException to prevent silent replacement of a real relation definition.

Solutions

  1. Rename your custom relation to a unique shortName not already used for that language
  2. Reuse the existing GrammaticalRelation constant instead of constructing a duplicate
  3. If you intentionally want to shadow a relation, ensure it is created via fromString (isFromString) so replacement is allowed
  4. Clear/restart the JVM state if duplicated definitions were loaded by accident in a long-running process

Example fix

// before
new GrammaticalRelation(Language.English, "nsubj", "my subject", ...); // clashes with built-in nsubj
// after
new GrammaticalRelation(Language.English, "my-nsubj", "my subject", ...);
Defensive patterns

Strategy: validation

Validate before calling

GrammaticalRelation existing = GrammaticalRelation.valueOf(lang, shortName);
if (existing != null && !existing.isFromString()) {
    throw new IllegalStateException("Relation name already taken: " + shortName);
}

Try / catch

try {
    GrammaticalRelation r = new GrammaticalRelation(lang, shortName, ...);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("There is already a relation named")) {
        r = GrammaticalRelation.valueOf(lang, shortName); // reuse existing
    } else throw e;
}

Prevention

When it happens

Trigger: Constructing two GrammaticalRelation objects with the same shortName/language where the pre-existing one is a genuine (not fromString) relation; re-running class initialization or reflection-based code that redefines built-in relations like GOVERNOR or DEPENDENT in the same JVM.

Common situations: Custom relation classes defined twice (e.g. copy-pasted definition in two classes); loading user relations that clash with built-in names like 'nsubj' or 'dep'; hot-reloading classes within one JVM where the static map persists.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/trees/GrammaticalRelation.java:322

        TregexPattern p = tregexCompiler.compile(pattern);
        this.targetPatterns.add(p);
      } catch (edu.stanford.nlp.trees.tregex.TregexParseException pe) {
        throw new RuntimeException("Bad pattern: " + pattern, pe);
      }
    }

    GrammaticalRelation previous;
    synchronized (stringsToRelations) {
      Map<String, GrammaticalRelation> sToR = stringsToRelations.get(language);
      if (sToR == null) {
        sToR = Generics.newHashMap();
        stringsToRelations.put(language, sToR);
      }
      previous = sToR.put(toString(), this);
    }
    if (previous != null) {
      if ( ! previous.isFromString() && ! isFromString()) {
        throw new IllegalArgumentException("There is already a relation named " + this + '!');
      } else {
        /* We get here if we previously just built a fake relation from a string
         * we previously read in from a file.
         */
        // TODO is it worth copying all of the information from this real
        //      relation into the old fake one?
      }
    }
  }

  // This is the main constructor used
  public GrammaticalRelation(Language language,
                             String shortName,
                             String longName,
                             GrammaticalRelation parent,
                             String sourcePattern,
                             TregexPatternCompiler tregexCompiler,
                             String... targetPatterns) {

View on GitHub (pinned to 1b7edd19c4)