puppetlabs/puppet · error · ArgumentError

Invalid option '%{option}'

Error message

Invalid option '%{option}'

What it means

Fileset's initialize_from_hash dynamically calls `<option>=` for every key in the options hash. A key with no corresponding setter raises NoMethodError, which is re-raised as ArgumentError "Invalid option" with the original backtrace. Valid options map to existing attribute writers: path, ignore, links, recurse, recurselimit, max_files, checksum_type.

Source

Thrown at lib/puppet/file_serving/fileset.rb:108

  def links=(links)
    links = links.to_sym
    # TRANSLATORS ":links" is a parameter name and should not be translated
    raise(ArgumentError, _("Invalid :links value '%{links}'") % { links: links }) unless [:manage, :follow].include?(links)

    @links = links
    @stat_method = @links == :manage ? :lstat : :stat
  end

  private

  def initialize_from_hash(options)
    options.each do |option, value|
      method = option.to_s + "="
      begin
        send(method, value)
      rescue NoMethodError => e
        raise ArgumentError, _("Invalid option '%{option}'") % { option: option }, e.backtrace
      end
    end
  end

  def initialize_from_request(request)
    [:links, :ignore, :recurse, :recurselimit, :max_files, :checksum_type].each do |param|
      if request.options.include?(param) # use 'include?' so the values can be false
        value = request.options[param]
      elsif request.options.include?(param.to_s)
        value = request.options[param.to_s]
      end
      next if value.nil?

      value = true if value == "true"
      value = false if value == "false"
      value = Integer(value) if value.is_a?(String) and value =~ /^\d+$/
      send(param.to_s + "=", value)
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Check the key against the supported set (path, ignore, links, recurse, recurselimit, max_files, checksum_type) and fix the typo
  2. Whitelist keys before constructing: slice the hash to the known option names
  3. If you meant request-style options, pass a Puppet::Indirector::Request (initialize_from_request only reads known params) instead of a raw hash

Example fix

# before
opts = { recurse: true, recurselimit: 2, ignore_fire: '.git' }
fileset = Puppet::FileServing::Fileset.new('/srv/data', opts)

# after
opts = { recurse: true, recurselimit: 2, ignore: '.git' }
fileset = Puppet::FileServing::Fileset.new('/srv/data', opts)
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = %i[path ignore links recurse recurselimit max_files checksum_type].freeze
opts = opts.slice(*ALLOWED) # Hash#slice (Ruby 2.5+)
fileset = Puppet::FileServing::Fileset.new(path, opts)

Type guard

def valid_fileset_options?(opts)
  opts.is_a?(Hash) && opts.keys.all? { |k| ALLOWED.include?(k.to_sym) }
end

Try / catch

begin
  Puppet::FileServing::Fileset.new(path, opts)
rescue ArgumentError => e
  raise unless e.message.start_with?("Invalid option")
  bad = opts.keys.find { |k| !ALLOWED.include?(k.to_sym) }
  opts = opts.reject { |k, _| k.to_sym == bad.to_sym }
  retry
end

Prevention

When it happens

Trigger: Puppet::FileServing::Fileset.new('/x', recurse_limit: 2) (typo'd key); passing a generic options hash (from YAML/JSON or method args splats) that contains keys like `server` or `environment` that Fileset does not support.

Common situations: Forwarding option hashes meant for other classes into Fileset; typo'd symbol keys; configuration-driven code where the set of keys drifts from the Fileset API after a Puppet upgrade.

Related errors


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