{"record":{"id":"22570243ecb339b9","repo":"stanfordnlp/CoreNLP","slug":"multiple-declarations-of-option","errorCode":null,"errorMessage":"Multiple declarations of option ","messagePattern":"Multiple declarations of option ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/util/ArgumentParser.java","lineNumber":404,"sourceCode":"          }\n          if (canFill.containsKey(name)) {\n            String name1 = canFill.get(name).getDeclaringClass().getCanonicalName() + '.' + canFill.get(name).getName();\n            String name2 = f.getDeclaringClass().getCanonicalName() + '.' + f.getName();\n            if (!name1.equals(name2)) {\n              runtimeException(\"Multiple declarations of option \" + name + \": \" + name1 + \" and \" + name2);\n            } else {\n              err(\"Class is in classpath multiple times: \" + canFill.get(name).getDeclaringClass().getCanonicalName());\n            }\n          }\n          canFill.put(name, f);\n          required.put(name, mark);\n          interner.put(name, name);\n          //(add alternate names)\n          if ( ! o.alt().isEmpty()) {\n            for (String alt : o.alt().split(\" *, *\")) {\n              alt = alt.toLowerCase();\n              if (canFill.containsKey(alt) && !alt.equals(name))\n                throw new IllegalArgumentException(\"Multiple declarations of option \" + alt + \": \" + canFill.get(alt) + \" and \" + f);\n              canFill.put(alt, f);\n              if (mark.first) required.put(alt, mark);\n              interner.put(alt, name);\n            }\n          }\n        }\n      }\n      //(check to ensure that something got filled, if any @Option annotation was found)\n      if (someOptionFound && !someOptionFilled) {\n        warn(\"found @Option annotations in class \" + c + \", but didn't set any of them (all options were instance variables and no instance given?)\");\n      }\n    }\n\n    //--Fill Options\n    for (Map.Entry<Object, Object> entry : options.entrySet()) {\n      String rawKeyStr = entry.getKey().toString();\n      String key = rawKeyStr.toLowerCase();\n      // (get values)","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/util/ArgumentParser.java#L386-L422","documentation":"ArgumentParser.fillOptionsImpl builds a map of fillable option names from @Option-annotated fields. When two fields (or an alternate name of two fields) declare the same option name, this IllegalArgumentException is thrown, naming the duplicated option and both declaring fields. It prevents ambiguous option binding at program startup.","triggerScenarios":"Two @Option fields with the same name, or two classes' fields whose alt names collide, passed to fillOptions/fillOptionsImpl via bootstrapMap — detected when canFill already contains the alt name and it isn't the same field's own name.","commonSituations":"Refactoring a class so two fields end up with the same option name; composing multiple option-holder classes that share an option name; renaming a field without updating alt names so an alt collides with another field's name.","solutions":["Read the message: rename one of the two fields listed so each @Option name/alt is unique.","Adjust the alt() lists to remove the colliding alternate name.","If composing classes, ensure each contributes distinct option names before calling fillOptions.","Add a startup self-test that calls fillOptions once to surface collisions early."],"exampleFix":"// before\n@Option(name = \"verbose\", alt = \"v\") public boolean verbose;\n@Option(name = \"verbose\") public boolean debugMode;\n// after\n@Option(name = \"verbose\", alt = \"v\") public boolean verbose;\n@Option(name = \"debug-mode\") public boolean debugMode;","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (Field f : clazz.getDeclaredFields()) {\n  Option o = f.getAnnotation(Option.class);\n  if (o == null) continue;\n  if (!seen.add(o.name())) throw new IllegalStateException(\"Duplicate option: \" + o.name());\n}","typeGuard":null,"tryCatchPattern":"try { ArgumentParser.fillOptions(opts, props); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Multiple declarations of option\")) { throw new IllegalStateException(\"Fix duplicate @Option in \" + opts.getClass(), e); } throw e; }","preventionTips":["Grep @Option names/alt lists for duplicates when adding fields.","When composing option classes, run a one-time fillOptions smoke test at startup.","Rename fields and alts together during refactors."],"tags":["configuration","argument-parser","duplicate-option","reflection"],"backgroundTag":"conflicting-config-options","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"}