puppetlabs/puppet · error · ArgumentError

Invalid recurse value %{value}

Error message

Invalid recurse value %{value}

What it means

tidy's `recurse` parameter deliberately replaces the inherited validation with a no-op (`validate { |arg| }`) and re-implements it in munge (lib/puppet/type/tidy.rb:52): true/false/inf become booleans, Integers and digit-only strings become a depth limit; everything else raises ArgumentError "Invalid recurse value". Unlike file's recurse, 'remote'/'local' are NOT accepted.

Source

Thrown at lib/puppet/type/tidy.rb:52

    desc "If target is a directory, recursively descend
      into the directory looking for files to tidy. Numeric values
      specify a limit for the recursion depth, `true` means
      unrestricted recursion."

    newvalues(:true, :false, :inf, /^[0-9]+$/)

    # Replace the validation so that we allow numbers in
    # addition to string representations of them.
    validate { |arg| }
    munge do |value|
      newval = super(value)
      case newval
      when :true, :inf; true
      when :false; false
      when Integer; value
      when /^\d+$/; Integer(value)
      else
        raise ArgumentError, _("Invalid recurse value %{value}") % { value: value.inspect }
      end
    end
  end

  newparam(:max_files) do
    desc "In case the resource is a directory and the recursion is enabled, puppet will
      generate a new resource for each file file found, possible leading to
      an excessive number of resources generated without any control.

      Setting `max_files` will check the number of file resources that
      will eventually be created and will raise a resource argument error if the
      limit will be exceeded.

      Use value `0` to disable the check. In this case, a warning is logged if
      the number of files exceeds 1000."

    defaultto 0
    newvalues(/^[0-9]+$/)

View on GitHub (pinned to e227c27540)

Solutions

  1. Use `true`/`false`, `inf`, or an integer depth (e.g. recurse => 2)
  2. Use recurse => true or inf for unlimited depth
  3. Remember tidy has no 'remote' recursion — that is file-only vocabulary

Example fix

# before
tidy { '/var/opt/app/tmp':
  recurse => 'yes',
}

# after
tidy { '/var/opt/app/tmp':
  recurse => true,
}
Defensive patterns

Strategy: validation

Validate before calling

if $recurse != undef and !($recurse =~ /\A\d+\z/ or $recurse in [true, false, 'true', 'false', 'inf']) {
  fail("tidy recurse must be true/false/inf or an integer, got '${recurse}'")
}

Type guard

def valid_tidy_recurse?(v)
  v == true || v == false || v.is_a?(Integer) ||
    %w[true false inf].include?(v.to_s) || v.to_s =~ /\A\d+\z/
end

Try / catch

begin
  Puppet::Type.type(:tidy).new(path: '/tmp/x', recurse: 'remote')
rescue ArgumentError => e
  raise unless e.message.include?('recurse')
  # substitute true/inf or an integer depth
end

Prevention

When it happens

Trigger: `tidy { '/var/tmp': recurse => 'remote' }` (valid on file resources, invalid on tidy); `recurse => 'yes'`; `recurse => 1.5`; symbols.

Common situations: Copying recurse => remote from file resources; expecting boolean synonyms ('yes'/'no'); tidy examples confused with file's vocabulary.

Related errors


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