puppetlabs/puppet · error · Puppet::ParseError
Attempt to assign to a reserved variable name: '%{name}'
Error message
Attempt to assign to a reserved variable name: '%{name}' What it means
Raised by Scope#setvar when assigning to the reserved names 'trusted' or 'facts' without options[:privileged]. These hashes are injected once by the compiler from node facts and certificate data; user code must not overwrite them because every consumer (manifests, functions, Hiera interpolation of $facts/$trusted) trusts their origin. Only internal calls marked :privileged may set them.
Source
Thrown at lib/puppet/parser/scope.rb:784
TYPENAME_CLASS = 'Class'
TYPENAME_NODE = 'Node'
# Set a variable in the current scope. This will override settings
# in scopes above, but will not allow variables in the current scope
# to be reassigned.
# It's preferred that you use self[]= instead of this; only use this
# when you need to set options.
def setvar(name, value, options = EMPTY_HASH)
if name =~ /^[0-9]+$/
raise Puppet::ParseError, _("Cannot assign to a numeric match result variable '$%{name}'") % { name: name } # unless options[:ephemeral]
end
unless name.is_a? String
raise Puppet::ParseError, _("Scope variable name %{name} is a %{class_type}, not a string") % { name: name.inspect, class_type: name.class }
end
# Check for reserved variable names
if (name == VARNAME_TRUSTED || name == VARNAME_FACTS) && !options[:privileged]
raise Puppet::ParseError, _("Attempt to assign to a reserved variable name: '%{name}'") % { name: name }
end
# Check for server_facts reserved variable name
if name == VARNAME_SERVER_FACTS && !options[:privileged]
raise Puppet::ParseError, _("Attempt to assign to a reserved variable name: '%{name}'") % { name: name }
end
table = effective_symtable(options[:ephemeral])
if table.bound?(name)
error = Puppet::ParseError.new(_("Cannot reassign variable '$%{name}'") % { name: name })
error.file = options[:file] if options[:file]
error.line = options[:line] if options[:line]
raise error
end
table[name] = value
# Assign the qualified name in the environmentView on GitHub (pinned to e227c27540)
Solutions
- Read $facts/$trusted instead of assigning; derive a local variable: `$myfacts = $facts + { 'extra' => 'v' }` ( Puppet 4 hash merge via +).
- To add real facts, ship a custom fact (lib/facter/*.rb) so the value comes from the node itself.
- For test harnesses, inject facts at the node level (e.g. puppet apply --loadclasses-style node definitions, rspec-puppet's let(:facts)) rather than assigning in the manifest.
- If you truly are compiler-internal code, pass `privileged: true` to setvar.
Example fix
# before
$facts = { 'kernel' => 'Linux' } # Attempt to assign to a reserved variable name: 'facts'
# after
$local_facts = $facts + { 'extra_info' => 'value' }
notify { $local_facts['kernel']: } Defensive patterns
Strategy: validation
Validate before calling
# Before writing code, check the reserved list:
RESERVED = %w[trusted facts server_facts].freeze
raise ArgumentError, "reserved: #{n}" if RESERVED.include?(n)
# DSL: derive, don't assign:
$local = $facts + { 'extra' => 'v' } Prevention
- Treat $facts and $trusted as read-only node data; extend via custom facts (lib/facter) instead.
- In Ruby functions, never call scope.setvar on reserved names; pass privileged: true only in compiler internals.
- Lint for reserved-name assignments when upgrading old modules (rg '^\$?(facts|trusted)\s*=').
When it happens
Trigger: Manifest assignments `$facts = {...}`, `$facts['kernel'] = 'Linux'`, or `$trusted = {...}`. Ruby functions calling `scope.setvar('facts', hash)` or `scope['trusted'] = data` without `privileged: true` in the options hash. Also templates or defined types trying to 'extend' the facts hash by reassigning the whole variable.
Common situations: Modules written for very old Puppet (pre-3.5) where $facts did not exist and users emulated it; attempts to fake facts in tests or local apply runs; copying ENC output into $trusted during provisioning scripts.
Related errors
- Cannot assign to a numeric match result variable '$%{name}'
- Undefined variable '%{name}'; %{reason}
- Attempt to assign variable %{name} when evaluating parameter
- Undefined variable '%{name}'; %{reason}
- The attribute '%{name}' is reserved and cannot be used
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/561fe7f2457c8e3e.
Report an issue: GitHub.