puppetlabs/puppet · error · Puppet::DataBinding::LookupError
Unable to parse %{message}
Error message
Unable to parse %{message} What it means
While resolving Hiera data through the 'yaml_data' function, Puppet::Util::Yaml.safe_load raised a YamlLoadError (unparsable YAML, forbidden alias, or a disallowed Ruby object/tag). The function rescues it and re-raises as Puppet::DataBinding::LookupError prefixed 'Unable to parse', aborting the catalog compile. Unlike the not-a-hash case, this raises regardless of strict mode.
Source
Thrown at lib/puppet/functions/yaml_data.rb:38
param 'Puppet::LookupContext', :context
end
def yaml_data(options, context)
path = options['path']
context.cached_file_data(path) do |content|
data = Puppet::Util::Yaml.safe_load(content, [Symbol], path)
if data.is_a?(Hash)
Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data)
else
msg = _("%{path}: file does not contain a valid yaml hash" % { path: path })
raise Puppet::DataBinding::LookupError, msg if Puppet[:strict] == :error && data != false
Puppet.warning(msg)
{}
end
rescue Puppet::Util::Yaml::YamlLoadError => ex
# YamlLoadErrors include the absolute path to the file, so no need to add that
raise Puppet::DataBinding::LookupError, _("Unable to parse %{message}") % { message: ex.message }
end
end
def missing_path(options, context)
"one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function"
end
end
View on GitHub (pinned to e227c27540)
Solutions
- Reproduce the parse locally: ruby -ryaml -e "YAML.safe_load(File.read('file.yaml'), aliases: false)" — the YamlLoadError message embedded in 'Unable to parse %' includes the file and line.
- Remove YAML anchors and aliases; inline the repeated values.
- Replace tabs with spaces and fix indentation/quote errors reported at the given line.
- Use 'puppet lookup --explain' to confirm which matched path is the culprit when globs are involved.
Example fix
# before (safe_load rejects aliases) base: &base server: 'puppet.example.com' prod: <<: *base # after (inline the data) base: server: 'puppet.example.com' prod: server: 'puppet.example.com'
Defensive patterns
Strategy: validation
Validate before calling
require 'yaml'
def parseable?(path)
YAML.safe_load(File.read(path), permitted_classes: [Symbol], aliases: false)
true
rescue Psych::SyntaxError, StandardError => e
warn "#{path}: #{e.message}"
false
end
exit 1 unless Dir['data/**/*.yaml'].all? { |f| parseable?(f) } Try / catch
begin value = Puppet.lookup(:hiera).lookup(key, scope) rescue Puppet::DataBinding::LookupError => e # e.message starts with 'Unable to parse' and includes file/line raise if ENV['STRICT_HIERA'] default_value end
Prevention
- Never use YAML anchors/aliases in hiera data files; safe_load always rejects them.
- Editor: force spaces (never tabs) for YAML files.
- Add a YAML syntax check to pre-commit hooks for the datadir.
When it happens
Trigger: A matched YAML file contains anchors/aliases (&base / *ref), which safe_load rejects; tab characters used for indentation; unbalanced quotes or brackets; binary or corrupted file content; a wrong file pulled in by a glob or mapped_paths entry.
Common situations: Trying to DRY hiera files with YAML anchors (works in some external tools, rejected by safe_load); copy-pasting rendered ERB/EPP output that introduces tabs; a file truncated mid-deploy; symlinking non-hiera YAML into the datadir.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- %{path}: file does not contain a valid yaml hash
- Could not load external node results for %{name}: %{detail}
- Could not parse YAML data for %{indirection} %{request}: %{d
- Function lookup() did not find a value for the name '%{name}
- Recursive lookup detected in [%{name_stack}]
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/fa89536d39f31c12.
Report an issue: GitHub.