puppetlabs/puppet · error · ArgumentError
Given variables must be a hash, got %{type}
Error message
Given variables must be a hash, got %{type} What it means
PAL's add_variables injects caller-supplied variables into the evaluation scope. nil is a valid no-op, but any other non-Hash value raises ArgumentError reporting the actual class. The variables hash flows from the PAL entry points (variables: / target_variables: options) into the scope.
Source
Thrown at lib/puppet/pal/pal_impl.rb:378
# speeded up (as getting a fresh set of facts is avoided in a later step).
#
def self.prepare_node_facts(node, facts)
# Prepare the node with facts if it does not already have them
if node.facts.nil?
node_facts = facts.nil? ? nil : Puppet::Node::Facts.new(Puppet[:node_name_value], facts)
node.fact_merge(node_facts)
# Add server facts so $server_facts[environment] exists when doing a puppet script
# SCRIPT TODO: May be needed when running scripts under orchestrator. Leave it for now.
#
node.add_server_facts({})
end
end
private_class_method :prepare_node_facts
def self.add_variables(scope, variables)
return if variables.nil?
unless variables.is_a?(Hash)
raise ArgumentError, _("Given variables must be a hash, got %{type}") % { type: variables.class }
end
rich_data_t = Puppet::Pops::Types::TypeFactory.rich_data
variables.each_pair do |k, v|
unless k =~ Puppet::Pops::Patterns::VAR_NAME
raise ArgumentError, _("Given variable '%{varname}' has illegal name") % { varname: k }
end
unless rich_data_t.instance?(v)
raise ArgumentError, _("Given value for '%{varname}' has illegal type - got: %{type}") % { varname: k, type: v.class }
end
scope.setvar(k, v)
end
end
private_class_method :add_variables
# The main routine for script compilerView on GitHub (pinned to e227c27540)
Solutions
- Pass a Ruby Hash: variables: { 'debug' => true }
- Convert pair arrays with .to_h or Hash[...] before the call
- For JSON input, ensure JSON.parse returned an object ({}), not a scalar/array
Example fix
# before
Puppet::Pal.with_script_compiler(variables: config.to_s) { |c| }
# after
Puppet::Pal.with_script_compiler(variables: config.to_h) { |c| } Defensive patterns
Strategy: type-guard
Validate before calling
raise ArgumentError, "variables must be a Hash, got #{variables.class}" unless variables.is_a?(Hash) Type guard
def pal_variables?(v) v.nil? || v.is_a?(Hash) end
Prevention
- Convert JSON input with JSON.parse(x, object_class: Hash) and verify it is a Hash
- Never call .to_s on a hash you intend to pass as variables
When it happens
Trigger: variables: 'a=1' (String), variables: [['x', 1]] (array of pairs), or feeding JSON.parse output that is an Array/String directly to with_script_compiler/in_environment variables option.
Common situations: Passing serialized config (JSON/YAML fragments) without converting; .to_s applied to a hash; older tooling that passed key/value lists.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Given data_type value is not a data type, got '%{type}'
- manifest_file or code_string cannot be given when configured
- A block must be given to 'in_tmp_environment'
- A block must be given to 'in_environment'
- Given variable '%{varname}' has illegal name
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/1a564a96d18f7e32.
Report an issue: GitHub.