puppetlabs/puppet · error · ArgumentError

Option %{option} conflicts with existing option %{conflict}

Error message

Option %{option} conflicts with existing option %{conflict}

What it means

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.

Source

Thrown at lib/puppet/interface/option_manager.rb:60

  # details.
  #
  # @api public
  # @dsl Faces
  def option(*declaration, &block)
    add_option Puppet::Interface::OptionBuilder.build(self, *declaration, &block)
  end

  # @api private
  def add_option(option)
    # @options collects the added options in the order they're declared.
    # @options_hash collects the options keyed by alias for quick lookups.
    @options      ||= []
    @options_hash ||= {}

    option.aliases.each do |name|
      conflict = get_option(name)
      if conflict
        raise ArgumentError, _("Option %{option} conflicts with existing option %{conflict}") %
                             { option: option, conflict: conflict }
      end

      actions.each do |action|
        action = get_action(action)
        conflict = action.get_option(name)
        if conflict
          raise ArgumentError, _("Option %{option} conflicts with existing option %{conflict} on %{action}") %
                               { option: option, conflict: conflict, action: action }
        end
      end
    end

    @options << option.name

    option.aliases.each do |name|
      @options_hash[name] = option
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Rename or remove the colliding switch at the same level
  2. Pick a different short alias (e.g. -E instead of -e)
  3. When extending a face, drop the redeclaration and reuse the inherited option

Example fix

# before
option "--environment", "-e" do
  summary "Environment to operate in"
end
option "--encrypt", "-e" do
  summary "Encrypt output"
end

# after
option "--environment", "-e" do
  summary "Environment to operate in"
end
option "--encrypt", "-E" do
  summary "Encrypt output"
end
Defensive patterns

Strategy: validation

Validate before calling

# inside the define block, before declaring an option
name = :environment # underscored long-option name
raise ArgumentError, "option #{name} already exists on this face" if get_option(name)
option '--environment', '-e' do
  summary 'Environment to operate in'
end

Prevention

When it happens

Trigger: 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.

Common situations: Adding a convenient short flag that is already taken; copy-pasting option blocks; sub-faces redeclaring parent options.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/9bf7ae5ed8ad1b75. Report an issue: GitHub.