puppetlabs/puppet · error · ArgumentError

invalid long option name %{name}

Error message

invalid long option name %{name}

What it means

Parser#opt computes each option's long name from :long (or from the symbol name with underscores converted to dashes) and validates its shape at trollop.rb:221-229: it must be a bare name whose first character is not a dash, or a name prefixed with exactly two dashes followed by a non-dash character. A value like '-x', '---verbose', or '--' matches neither alternative and raises ArgumentError at line 228.

Source

Thrown at lib/puppet/util/command_line/trollop.rb:228

        when nil; nil
        else
          raise ArgumentError, _("unsupported argument type '%{value0}'") % { value0: opts[:default].class.name }
        end

      raise ArgumentError, _(":type specification and default type don't match (default type is %{type_from_default})") % { type_from_default: type_from_default } if opts[:type] && type_from_default && opts[:type] != type_from_default

      opts[:type] = opts[:type] || type_from_default || :flag

      ## fill in :long
      opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.tr("_", "-")
      opts[:long] =
        case opts[:long]
        when /^--([^-].*)$/
          ::Regexp.last_match(1)
        when /^[^-]/
          opts[:long]
        else
          raise ArgumentError, _("invalid long option name %{name}") % { name: opts[:long].inspect }
        end
      raise ArgumentError, _("long option name %{value0} is already taken; please specify a (different) :long") % { value0: opts[:long].inspect } if @long[opts[:long]]

      ## fill in :short
      unless opts[:short] == :none
        opts[:short] = opts[:short].to_s if opts[:short]
      end
      opts[:short] = case opts[:short]
                     when /^-(.)$/; ::Regexp.last_match(1)
                     when nil, :none, /^.$/; opts[:short]
                     else raise ArgumentError, _("invalid short option name '%{name}'") % { name: opts[:short].inspect }
                     end

      if opts[:short]
        raise ArgumentError, _("short option name %{value0} is already taken; please specify a (different) :short") % { value0: opts[:short].inspect } if @short[opts[:short]]
        raise ArgumentError, _("a short option name can't be a number or a dash") if opts[:short] =~ INVALID_SHORT_ARG_REGEX
      end

View on GitHub (pinned to e227c27540)

Solutions

  1. Pass :long with no dashes at all (`long: 'verbose'`) or with exactly two leading dashes (`long: '--verbose'`)
  2. Drop :long and let the symbol drive the name (opt :verbose yields '--verbose' automatically)
  3. Sanitize programmatically generated names to letters, digits, and internal dashes before declaring them

Example fix

# before
opt :verbose, 'Verbosity', long: '-verbose'

# after
opt :verbose, 'Verbosity'          # derives '--verbose'
# or explicitly:
opt :verbose, 'Verbosity', long: '--verbose'
Defensive patterns

Strategy: validation

Validate before calling

# Normalize/validate a :long value (or derived name) before opt
def valid_long?(long)
  long = long.to_s
  long =~ /^--([^-].*)$/ || long =~ /^[^-]/
end

long = opts.fetch(:long) { name.to_s.tr('_', '-') }
raise ArgumentError, "bad long name #{long.inspect}" unless valid_long?(long)

Try / catch

begin
  parser.opt name, desc, long: candidate
rescue ArgumentError => e
  raise unless e.message.include?('invalid long option name')
  parser.opt name, desc   # fall back to the symbol-derived name
end

Prevention

When it happens

Trigger: `opt :x, 'desc', long: '-x'` (single leading dash); `long: '---verbose'`; `long: '--'`; a symbol such as :'-foo' whose name becomes '-foo' after tr('_', '-').

Common situations: Porting specs from Ruby's OptionParser where '-x'-style strings were the convention; building option names programmatically from user-supplied strings without sanitizing leading dashes.

Related errors


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