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

  1. Move the Trollop::options { ... } block so it runs before any Trollop::die call
  2. If validation must happen early, parse options first and then die based on the parsed values or ARGV
  3. 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

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


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