puppetlabs/puppet · error · ArgumentError
Trollop::die can only be called after Trollop::options
Error message
Trollop::die can only be called after Trollop::options
What it means
Trollop::die is the module-level helper that reports a fatal usage error, but it only works after Trollop::options has created a parser: die delegates to the @last_parser registered by the most recent options block. If die is called before any options block has run, @last_parser is nil and ArgumentError is raised instead of the intended error message. The problem is purely the order of calls in the embedding application.
Source
Thrown at lib/puppet/util/command_line/trollop.rb:839
## end
##
## die :volume, "too loud" if opts[:volume] > 10.0
## die :volume, "too soft" if opts[:volume] < 0.1
##
## In the one-argument case, simply print that message, a notice
## about -h, and die. Example:
##
## options do
## opt :whatever # ...
## end
##
## Trollop::die "need at least one filename" if ARGV.empty?
def die arg, msg = nil
if @last_parser
@last_parser.die arg, msg
else
# TRANSLATORS 'Trollop' is the name of a module and 'die' and 'options' are methods in it and should not be translated.
raise ArgumentError, _("Trollop::die can only be called after Trollop::options")
end
end
module_function :options, :die, :with_standard_exception_handling
end # module
end
end
end
View on GitHub (pinned to e227c27540)
Solutions
- Move the Trollop::options { ... } block so it runs before any Trollop::die call
- If validation must happen early, parse options first and then die based on the parsed values or ARGV
- Wrap the CLI entry point in with_standard_exception_handling so usage problems print help instead of a Ruby backtrace
Example fix
# before
Trollop::die 'need at least one filename' if ARGV.empty?
opts = Trollop.options { opt :verbose, 'Verbose' }
# => ArgumentError: Trollop::die can only be called after Trollop::options
# after
opts = Trollop.options { opt :verbose, 'Verbose' }
Trollop::die 'need at least one filename' if ARGV.empty? Defensive patterns
Strategy: validation
Validate before calling
opts = Trollop.options do opt :verbose, 'Run verbosely' end # Trollop::die is only safe after this call
Try / catch
begin
Trollop::die('need a file') if ARGV.empty?
rescue ArgumentError => e
abort "CLI bug: #{e.message} (parse options before die)"
end Prevention
- Always create the parser with Trollop::options before any Trollop::die call
- Keep argument validation immediately after option parsing so the order is obvious
When it happens
Trigger: A bin script or custom Puppet face that calls Trollop::die('need at least one filename') before ever calling Trollop::options { ... }, typically after a refactor hoists early validation above the parser setup, or when the documented example is copied without its options block.
Common situations: Refactors that move argument validation above option parsing, copy-pasting the Trollop usage example without the options block, and code paths that conditionally skip Trollop.options but unconditionally call die.
Related errors
- Error parsing arguments
- unsupported argument type '%{value0}'
- :type specification and default type don't match (default ty
- invalid long option name %{name}
- long option name %{value0} is already taken; please specify
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/2df94bb7a2d48572.
Report an issue: GitHub.