{"record":{"id":"9bf7ae5ed8ad1b75","repo":"puppetlabs/puppet","slug":"option-option-conflicts-with-existing-option-9bf7ae","errorCode":null,"errorMessage":"Option %{option} conflicts with existing option %{conflict}","messagePattern":"Option %(.+?) conflicts with existing option %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/interface/option_manager.rb","lineNumber":60,"sourceCode":"  # details.\n  #\n  # @api public\n  # @dsl Faces\n  def option(*declaration, &block)\n    add_option Puppet::Interface::OptionBuilder.build(self, *declaration, &block)\n  end\n\n  # @api private\n  def add_option(option)\n    # @options collects the added options in the order they're declared.\n    # @options_hash collects the options keyed by alias for quick lookups.\n    @options      ||= []\n    @options_hash ||= {}\n\n    option.aliases.each do |name|\n      conflict = get_option(name)\n      if conflict\n        raise ArgumentError, _(\"Option %{option} conflicts with existing option %{conflict}\") %\n                             { option: option, conflict: conflict }\n      end\n\n      actions.each do |action|\n        action = get_action(action)\n        conflict = action.get_option(name)\n        if conflict\n          raise ArgumentError, _(\"Option %{option} conflicts with existing option %{conflict} on %{action}\") %\n                               { option: option, conflict: conflict, action: action }\n        end\n      end\n    end\n\n    @options << option.name\n\n    option.aliases.each do |name|\n      @options_hash[name] = option\n    end","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/interface/option_manager.rb#L42-L78","documentation":"OptionManager#add_option registers a face- (or action-) level option and first checks every alias — the option name plus each declared switch — against options already registered on the same level via get_option (lib/puppet/interface/option_manager.rb:60). Any collision, including inherited options from a parent face, raises ArgumentError naming both options, because the alias-keyed options_hash lookup must stay unambiguous.","triggerScenarios":"Two face-level options sharing a switch: `option '--environment', '-e'` and later `option '--encrypt', '-e'`; redeclaring an option inherited from a face you build upon; an option whose long name equals an existing option's alias.","commonSituations":"Adding a convenient short flag that is already taken; copy-pasting option blocks; sub-faces redeclaring parent options.","solutions":["Rename or remove the colliding switch at the same level","Pick a different short alias (e.g. -E instead of -e)","When extending a face, drop the redeclaration and reuse the inherited option"],"exampleFix":"# before\noption \"--environment\", \"-e\" do\n  summary \"Environment to operate in\"\nend\noption \"--encrypt\", \"-e\" do\n  summary \"Encrypt output\"\nend\n\n# after\noption \"--environment\", \"-e\" do\n  summary \"Environment to operate in\"\nend\noption \"--encrypt\", \"-E\" do\n  summary \"Encrypt output\"\nend","handlingStrategy":"validation","validationCode":"# inside the define block, before declaring an option\nname = :environment # underscored long-option name\nraise ArgumentError, \"option #{name} already exists on this face\" if get_option(name)\noption '--environment', '-e' do\n  summary 'Environment to operate in'\nend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check `get_option(name)` (nil means free) before declaring shared or short switches","Audit short aliases like -e before adding a new option","When extending a face, list inherited options first and avoid redeclaring them"],"tags":["puppet","faces","option","name-collision","argumenterror"],"backgroundTag":"duplicate-option-declaration","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}