{"record":{"id":"1f5c8db960e2b89a","repo":"puppetlabs/puppet","slug":"undefined-variable-name-reason-1f5c8d","errorCode":null,"errorMessage":"Undefined variable '%{name}'; %{reason}","messagePattern":"Undefined variable '%(.+?)'; %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/parser/scope.rb","lineNumber":542,"sourceCode":"    if BUILT_IN_VARS.include?(name) || name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME\n      return nil\n    end\n\n    begin\n      throw(:undefined_variable, reason)\n    rescue UNCAUGHT_THROW_EXCEPTION\n      case Puppet[:strict]\n      when :off\n        # do nothing\n      when :warning\n        Puppet.warn_once(UNDEFINED_VARIABLES_KIND, _(\"Variable: %{name}\") % { name: name },\n                         _(\"Undefined variable '%{name}'; %{reason}\") % { name: name, reason: reason })\n      when :error\n        if Puppet.lookup(:avoid_hiera_interpolation_errors) { false }\n          Puppet.warn_once(UNDEFINED_VARIABLES_KIND, _(\"Variable: %{name}\") % { name: name },\n                           _(\"Interpolation failed with '%{name}', but compilation continuing; %{reason}\") % { name: name, reason: reason })\n        else\n          raise ArgumentError, _(\"Undefined variable '%{name}'; %{reason}\") % { name: name, reason: reason }\n        end\n      end\n    end\n    nil\n  end\n\n  # Retrieves the variable value assigned to the name given as an argument. The name must be a String,\n  # and namespace can be qualified with '::'. The value is looked up in this scope, its parent scopes,\n  # or in a specific visible named scope.\n  #\n  # @param varname [String] the name of the variable (may be a qualified name using `(ns'::')*varname`\n  # @param options [Hash] Additional options, not part of api.\n  # @return [Object] the value assigned to the given varname\n  # @see #[]=\n  # @api public\n  #\n  def [](varname, options = EMPTY_HASH)\n    lookupvar(varname, options)","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/parser/scope.rb#L524-L560","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before\nfile { $config_dir: ensure => directory }   # $config_dir never set -> Undefined variable\n\n# after\n$config_dir = pick(getvar('app::config_dir'), '/etc/app')\nfile { $config_dir: ensure => directory }","handlingStrategy":"validation","validationCode":"# Guard optional lookups instead of bare references:\n$val = getvar('maybe::missing')            # returns undef, never raises\n# or with a default:\n$val = pick_default(getvar('x'), 'fallback')\n# check before use:\nnotify { 'ok': unless => getvar('x') == undef }","typeGuard":null,"tryCatchPattern":"# Ruby embedding:\nbegin\n  scope.lookupvar('maybe')\nrescue ArgumentError => e\n  # strict_variables miss — treat as nil\n  value = nil\nend","preventionTips":["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)."],"tags":["puppet","variables","strict-mode","scope","hiera"],"backgroundTag":"undefined-variable","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}