{"record":{"id":"ecdedf98d74ddc64","repo":"stanfordnlp/CoreNLP","slug":"there-is-already-a-relation-named-relation","errorCode":null,"errorMessage":"There is already a relation named <relation>!","messagePattern":"There is already a relation named <relation>!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/GrammaticalRelation.java","lineNumber":322,"sourceCode":"        TregexPattern p = tregexCompiler.compile(pattern);\n        this.targetPatterns.add(p);\n      } catch (edu.stanford.nlp.trees.tregex.TregexParseException pe) {\n        throw new RuntimeException(\"Bad pattern: \" + pattern, pe);\n      }\n    }\n\n    GrammaticalRelation previous;\n    synchronized (stringsToRelations) {\n      Map<String, GrammaticalRelation> sToR = stringsToRelations.get(language);\n      if (sToR == null) {\n        sToR = Generics.newHashMap();\n        stringsToRelations.put(language, sToR);\n      }\n      previous = sToR.put(toString(), this);\n    }\n    if (previous != null) {\n      if ( ! previous.isFromString() && ! isFromString()) {\n        throw new IllegalArgumentException(\"There is already a relation named \" + this + '!');\n      } else {\n        /* We get here if we previously just built a fake relation from a string\n         * we previously read in from a file.\n         */\n        // TODO is it worth copying all of the information from this real\n        //      relation into the old fake one?\n      }\n    }\n  }\n\n  // This is the main constructor used\n  public GrammaticalRelation(Language language,\n                             String shortName,\n                             String longName,\n                             GrammaticalRelation parent,\n                             String sourcePattern,\n                             TregexPatternCompiler tregexCompiler,\n                             String... targetPatterns) {","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/GrammaticalRelation.java#L304-L340","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename your custom relation to a unique shortName not already used for that language","Reuse the existing GrammaticalRelation constant instead of constructing a duplicate","If you intentionally want to shadow a relation, ensure it is created via fromString (isFromString) so replacement is allowed","Clear/restart the JVM state if duplicated definitions were loaded by accident in a long-running process"],"exampleFix":"// before\nnew GrammaticalRelation(Language.English, \"nsubj\", \"my subject\", ...); // clashes with built-in nsubj\n// after\nnew GrammaticalRelation(Language.English, \"my-nsubj\", \"my subject\", ...);","handlingStrategy":"validation","validationCode":"GrammaticalRelation existing = GrammaticalRelation.valueOf(lang, shortName);\nif (existing != null && !existing.isFromString()) {\n    throw new IllegalStateException(\"Relation name already taken: \" + shortName);\n}","typeGuard":null,"tryCatchPattern":"try {\n    GrammaticalRelation r = new GrammaticalRelation(lang, shortName, ...);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"There is already a relation named\")) {\n        r = GrammaticalRelation.valueOf(lang, shortName); // reuse existing\n    } else throw e;\n}","preventionTips":["Prefix custom relation names with a project-specific namespace","Check GrammaticalRelation.valueOf for the name before defining a new relation","Avoid re-running relation-defining static initializers twice in one JVM","Keep built-in relation names reserved"],"tags":["java","duplicate","naming","grammar"],"backgroundTag":"duplicate-identifier","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}