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
- Fix the reference: correct the typo/case, or reference the variable in the scope where it was set (or qualify it as $otherclass::var).
- Provide a fallback: `$x = getvar('maybe', 'default')` or `$x = pick(getvar('maybe'), 'default')` (stdlib pick) instead of a bare reference.
- Set the variable before use: assign it, or add the corresponding Hiera key / automatic data lookup binding.
- 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
- Run dev/prod with strict_variables=true from day one so misses appear immediately.
- Use getvar()/pick() for genuinely optional variables; use bare references only for guaranteed ones.
- Set variables at the narrowest scope that needs them, or fully qualify ($class::var) to avoid scope-walk surprises.
- Grep for interpolation of variables never assigned: `puppet parser validate` plus lint rules (strict_variables check in puppet-lint).
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
- Undefined variable '%{name}'; %{reason}
- Cannot assign to a numeric match result variable '$%{name}'
- Could not find data item %{key} in any Hiera data file and n
- Please supply a parameter to perform a Hiera lookup
- %{path}: file does not contain a valid yaml hash
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/1f5c8db960e2b89a.
Report an issue: GitHub.