puppetlabs/puppet · error · ArgumentError

Undefined variable '%{name}'; %{reason}

Error message

Undefined variable '%{name}'; %{reason}

What it means

Raised by Scope#variable_not_found when a variable lookup walks to the top of the scope chain without finding a binding and Puppet[:strict] is :error. lookupvar() (backing scope['name'] and $name interpolation) calls it after parent scopes are exhausted; under strict_variables the uncaught :undefined_variable throw becomes this ArgumentError instead of a silent nil. It is the enforcement point for Puppet's strict_variables mode.

Source

Thrown at lib/puppet/parser/scope.rb:542

    if BUILT_IN_VARS.include?(name) || name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME
      return nil
    end

    begin
      throw(:undefined_variable, reason)
    rescue UNCAUGHT_THROW_EXCEPTION
      case Puppet[:strict]
      when :off
        # do nothing
      when :warning
        Puppet.warn_once(UNDEFINED_VARIABLES_KIND, _("Variable: %{name}") % { name: name },
                         _("Undefined variable '%{name}'; %{reason}") % { name: name, reason: reason })
      when :error
        if Puppet.lookup(:avoid_hiera_interpolation_errors) { false }
          Puppet.warn_once(UNDEFINED_VARIABLES_KIND, _("Variable: %{name}") % { name: name },
                           _("Interpolation failed with '%{name}', but compilation continuing; %{reason}") % { name: name, reason: reason })
        else
          raise ArgumentError, _("Undefined variable '%{name}'; %{reason}") % { name: name, reason: reason }
        end
      end
    end
    nil
  end

  # Retrieves the variable value assigned to the name given as an argument. The name must be a String,
  # and namespace can be qualified with '::'. The value is looked up in this scope, its parent scopes,
  # or in a specific visible named scope.
  #
  # @param varname [String] the name of the variable (may be a qualified name using `(ns'::')*varname`
  # @param options [Hash] Additional options, not part of api.
  # @return [Object] the value assigned to the given varname
  # @see #[]=
  # @api public
  #
  def [](varname, options = EMPTY_HASH)
    lookupvar(varname, options)

View on GitHub (pinned to e227c27540)

Solutions

  1. Fix the reference: correct the typo/case, or reference the variable in the scope where it was set (or qualify it as $otherclass::var).
  2. Provide a fallback: `$x = getvar('maybe', 'default')` or `$x = pick(getvar('maybe'), 'default')` (stdlib pick) instead of a bare reference.
  3. Set the variable before use: assign it, or add the corresponding Hiera key / automatic data lookup binding.
  4. Transition tactic: set `strict_variables = false` in puppet.conf to surface all occurrences as warnings first, fix them, then re-enable.

Example fix

# before
file { $config_dir: ensure => directory }   # $config_dir never set -> Undefined variable

# after
$config_dir = pick(getvar('app::config_dir'), '/etc/app')
file { $config_dir: ensure => directory }
Defensive patterns

Strategy: validation

Validate before calling

# Guard optional lookups instead of bare references:
$val = getvar('maybe::missing')            # returns undef, never raises
# or with a default:
$val = pick_default(getvar('x'), 'fallback')
# check before use:
notify { 'ok': unless => getvar('x') == undef }

Try / catch

# Ruby embedding:
begin
  scope.lookupvar('maybe')
rescue ArgumentError => e
  # strict_variables miss — treat as nil
  value = nil
end

Prevention

When it happens

Trigger: Running with `strict_variables = true` (puppet.conf, or ScriptCompiler#compile which force-sets it) and referencing `$typo_var`, `'string ${missing}'` interpolation, or `scope['undefined_name']` from a function. Also `lookupvar('nope')` in Ruby. The :off/:warning strict levels instead stay silent or emit a warn_once 'Undefined variable' warning; only :error raises (unless avoid_hiera_interpolation_errors is in effect for hiera interpolation).

Common situations: Enabling strict_variables while migrating Puppet 3 modules that relied on undefined variables being nil; typos and case mistakes ($myVar vs $myvar); referencing a variable set in a different scope (e.g. inside a defined type or another class); expecting Hiera data to define a variable that has no binding; running scripts via `puppet apply`/`puppet script` which enable strict mode automatically.

Related errors


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