puppetlabs/puppet · error · ArgumentError

unknown option '%{sym}'

Error message

unknown option '%{sym}'

What it means

depends(*syms) records an undirected must-appear-together constraint between options. Before recording it, trollop.rb:277 verifies that each symbol is already present in @specs (registered by an earlier opt call) and raises ArgumentError for any unknown symbol. The eager check exists because constraints are resolved by symbol at parse time — a typo there would otherwise fail silently, so Trollop fails fast at declaration time.

Source

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

      @specs[name] = opts
      @order << [:opt, name]
    end

    ## Sets the version string. If set, the user can request the version
    ## on the commandline. Should probably be of the form "<program name>
    ## <version number>".
    def version s = nil; @version = s if s; @version end

    ## Adds text to the help display. Can be interspersed with calls to
    ## #opt to build a multi-section help page.
    def banner s; @order << [:text, s] end
    alias :text :banner

    ## Marks two (or more!) options as requiring each other. Only handles
    ## undirected (i.e., mutual) dependencies. Directed dependencies are
    ## better modeled with Trollop::die.
    def depends *syms
      syms.each { |sym| raise ArgumentError, _("unknown option '%{sym}'") % { sym: sym } unless @specs[sym] }
      @constraints << [:depends, syms]
    end

    ## Marks two (or more!) options as conflicting.
    def conflicts *syms
      syms.each { |sym| raise ArgumentError, _("unknown option '%{sym}'") % { sym: sym } unless @specs[sym] }
      @constraints << [:conflicts, syms]
    end

    ## Defines a set of words which cause parsing to terminate when
    ## encountered, such that any options to the left of the word are
    ## parsed as usual, and options to the right of the word are left
    ## intact.
    ##
    ## A typical use case would be for subcommand support, where these
    ## would be set to the list of subcommands. A subsequent Trollop
    ## invocation would then be used to parse subcommand options, after
    ## shifting the subcommand off of ARGV.

View on GitHub (pinned to e227c27540)

Solutions

  1. Declare every referenced option with opt before calling depends — declaration order matters
  2. Use the exact symbol from the opt declaration, not a string or the long name
  3. Remove constraint entries that reference options you renamed or deleted

Example fix

# before
opt :mode, 'Mode', type: :string
depends :mode, :intensity   # :intensity never declared -> raise

# after
opt :mode, 'Mode', type: :string
opt :intensity, 'Intensity', type: :int
depends :mode, :intensity
Defensive patterns

Strategy: validation

Validate before calling

# Validate constraint symbols against registered options before calling depends
declared = parser.instance_variable_get(:@specs).keys
missing = [:mode, :intensity].reject { |s| declared.include?(s) }
raise ArgumentError, "depends references undeclared options: #{missing.join(', ')}" unless missing.empty?
parser.depends :mode, :intensity

Try / catch

begin
  parser.depends :mode, :intensity
rescue ArgumentError => e
  raise unless e.message.include?("unknown option")
  # option not declared (yet) - declare it or drop the constraint
  parser.opt :intensity, 'Intensity', type: :int
  parser.depends :mode, :intensity
end

Prevention

When it happens

Trigger: `depends :mode, :intensity` when :intensity was never declared, is declared only after the depends call (declaration order matters), or is passed as the string 'intensity' instead of a symbol (strings never match @specs keys).

Common situations: Renaming an option and forgetting to update its constraint; declaring constraints above the opt calls; passing long-name strings ('--intensity') instead of option symbols.

Related errors


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