puppetlabs/puppet · error · Puppet::ParseError
Cannot assign to a numeric match result variable '$
Error message
Cannot assign to a numeric match result variable '$%{name}' What it means
Raised by Scope#setvar when the variable name consists solely of digits (matches /^[0-9]+$/). Numeric variable names $0..$n are reserved for regex match captures set by MatchScope; they are populated automatically when a =~ or !~ expression with capture groups runs, and Puppet forbids explicit assignment to them. Note this guard lives in setvar, so it applies to DSL assignments and Ruby functions alike.
Solutions
- Rename the variable to a non-numeric name: `$match1` instead of `$1`.
- If you want regex captures, trigger them with a match expression instead of assigning: `$content =~ /(a+)/` then read $1.
- In Ruby functions, reject or prefix numeric names before setvar: `name = "v#{name}" if name =~ /^[0-9]+$/`.
Example fix
# before $1 = 'primary' # Cannot assign to a numeric match result variable '$1' # after $primary = 'primary' # or set captures via an actual match: 'primary' =~ /^(.+)$/ # now $1 == 'primary'
Defensive patterns
Strategy: validation
Validate before calling
# Manifests: never use numeric names; if generating names programmatically:
# name = "v#{raw}" if raw =~ /^[0-9]+$/
# Ruby guard before assignment:
raise ArgumentError, 'numeric var' if name =~ /^[0-9]+$/
scope.setvar(name, value) unless name =~ /^[0-9]+$/ Prevention
- Reserve $0..$n exclusively for regex captures; use named captures (`$<name>`-style facts) or named variables otherwise.
- Sanitize external keys before creating scope variables from them.
- Read $0 only after a successful =~ match in the same scope.
When it happens
Trigger: Manifest code `$1 = 'foo'` or `$0 = generate_title()`; Ruby code calling `scope.setvar('2', 'x')` or `scope['3'] = value` on a parser scope. Also a function looping over user-supplied names that happen to be numeric strings.
Common situations: Porting templates/scripts that used numbered variables as throwaway names; Ruby functions auto-creating variables from external data (ERB, YAML keys like '1') without sanitizing names; confusing numeric match variables with regular variables in examples copied from regex-heavy manifests.
Related errors
- Attempt to assign to a reserved variable name
- Undefined variable ' ';
- Undefined variable ' ';
- Attempt to assign variable
- Given value for ' ' has illegal type - got
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/0d4f8a18e9f84062.
Report an issue: GitHub.
Appendix: source
Thrown at lib/puppet/parser/scope.rb:776
end
end
private :transform_setting
VARNAME_TRUSTED = 'trusted'
VARNAME_FACTS = 'facts'
VARNAME_SERVER_FACTS = 'server_facts'
RESERVED_VARIABLE_NAMES = [VARNAME_TRUSTED, VARNAME_FACTS].freeze
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 })View on GitHub (pinned to e227c27540)