puppetlabs/puppet · error · ArgumentError
a short option name can't be a number or a dash
Error message
a short option name can't be a number or a dash
What it means
INVALID_SHORT_ARG_REGEX is /[\d-]/ (trollop.rb:70). After the duplicate-character check, opt raises ArgumentError at trollop.rb:244 when the short option character is a digit or a dash. Digits are forbidden because a token like '-5' must stay consumable as a parameter (for example a negative number value for another option), and '-' is ambiguous with stdin-style conventions.
Source
Thrown at lib/puppet/util/command_line/trollop.rb:244
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
## fill in :default for flags
opts[:default] = false if opts[:type] == :flag && opts[:default].nil?
## autobox :default for :multi (multi-occurrence) arguments
opts[:default] = [opts[:default]] if opts[:default] && opts[:multi] && !opts[:default].is_a?(Array)
## fill in :multi
opts[:multi] ||= false
opts[:desc] ||= desc
@long[opts[:long]] = name
@short[opts[:short]] = name if opts[:short] && opts[:short] != :none
@specs[name] = opts
@order << [:opt, name]
end
View on GitHub (pinned to e227c27540)
Solutions
- Use a letter for the short form (`short: 'n'`)
- Drop :short and rely on the long form only
- Pass `short: :none` to skip the short form entirely
Example fix
# before opt :level, 'Level', short: '3' # after opt :level, 'Level', short: 'l'
Defensive patterns
Strategy: validation
Validate before calling
# Reject digit/dash short names before opt (mirrors INVALID_SHORT_ARG_REGEX /[\d-]/) raise ArgumentError, 'short option cannot be a digit or dash' if opts[:short].to_s =~ /[\d-]/ && opts[:short].to_s.length == 1
Try / catch
begin
parser.opt name, desc, short: candidate
rescue ArgumentError => e
raise unless e.message.include?("can't be a number or a dash")
parser.opt name, desc, short: candidate.to_s.tr('0-9-', 'abc').chars.first # or just drop it
end Prevention
- Never use digits or '-' as short flags - reserve them for values like negative numbers
- When porting legacy digit-flag CLIs, map digit flags to long options instead
When it happens
Trigger: `short: '3'`, `short: '0'`, or `short: '-'`.
Common situations: Numeric options where a digit feels mnemonic ('2' for two-way sync); porting legacy CLIs in the tar/od style whose classic flags were digits.
Related errors
- unsupported argument type '%{value0}'
- invalid long option name %{name}
- invalid short option name '%{name}'
- :type specification and default type don't match (default ty
- long option name %{value0} is already taken; please specify
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/1f7292d9a63b5cb3.
Report an issue: GitHub.