puppetlabs/puppet · error · ArgumentError

Tries must be an integer

Error message

Tries must be an integer

What it means

The Puppet `exec` type munges its `tries` parameter: when the value is a String it must match the digit-only regex /^\d+$/ before Integer() converts it. Any string containing letters, a sign, a decimal point, a comma, or whitespace raises this ArgumentError while the resource is being built or the catalog compiled.

Source

Thrown at lib/puppet/type/exec.rb:355

        rescue ArgumentError => e
          raise ArgumentError, _("The timeout must be a number."), e.backtrace
        end
        [value, 0.0].max
      end

      defaultto 300
    end

    newparam(:tries) do
      desc "The number of times execution of the command should be tried.
        This many attempts will be made to execute the command until an
        acceptable return code is returned. Note that the timeout parameter
        applies to each try rather than to the complete set of tries."

      munge do |value|
        if value.is_a?(String)
          unless value =~ /^\d+$/
            raise ArgumentError, _("Tries must be an integer")
          end

          value = Integer(value)
        end
        raise ArgumentError, _("Tries must be an integer >= 1") if value < 1

        value
      end

      defaultto 1
    end

    newparam(:try_sleep) do
      desc "The time to sleep in seconds between 'tries'."

      munge do |value|
        if value.is_a?(String)
          unless value =~ /^[-\d.]+$/

View on GitHub (pinned to e227c27540)

Solutions

  1. Set tries to a plain Integer: `tries => 3` (or a digit-only string such as '3').
  2. If the value comes from Hiera or a template, normalize before use: `tries => Integer($raw)`.
  3. Strip whitespace from strings: `tries => regsubst($raw, '\s', '', 'G')`.
  4. Catch it early with `puppet parser validate` or catalog compilation in CI.

Example fix

// before
exec { 'migrate':
  command => '/opt/app/migrate.sh',
  tries   => '3.0',   // '.' fails /^\d+$/
}

// after
exec { 'migrate':
  command => '/opt/app/migrate.sh',
  tries   => 3,
}
Defensive patterns

Strategy: validation

Validate before calling

// Puppet, before declaring the exec
unless $tries =~ Integer or ($tries =~ String and $tries =~ Pattern[/\A\d+\z/]) {
  fail("exec: tries must be an integer >= 1 or digit-only string, got '${tries}'")
}

Type guard

def valid_exec_tries?(v)
  v.is_a?(Integer) ? v >= 1 : v.is_a?(String) && v.match?(/\A\d+\z/) && v.to_i >= 1
end

Try / catch

When building resources in Ruby (Puppet::Type::Exec.new), wrap creation in begin/rescue ArgumentError and re-raise with the resource title for context; in manifests the error surfaces at compile time, so catch it with `puppet parser validate` in CI rather than at runtime.

Prevention

When it happens

Trigger: Declaring `exec { 'x': command => '...', tries => 'abc' }`; passing '1.5' or '2.0' (the '.' fails /^\d+$/); values like '-1', '+3', ' 3', '1,000', '0x10'; values interpolated from ERB/EPP templates or Hiera that arrive as "3\n". Bare Integers and digit-only strings pass.

Common situations: Hiera/YAML values stored as formatted strings; template interpolation appending newlines or spaces; attempts to express fractional retry counts; quoting habits from shell scripts carrying stray characters into the manifest.

Related errors


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