puppetlabs/puppet · error · Puppet::DataBinding::LookupError
%{path}: file does not contain a valid yaml hash
Error message
%{path}: file does not contain a valid yaml hash What it means
Puppet's built-in Hiera 'yaml_data' data_hash function loads each YAML file with Puppet::Util::Yaml.safe_load and expects a top-level mapping. If the document is anything other than a Hash (a sequence, a scalar, or a comments-only file that parses as nil), the data cannot serve key lookups: under strict=error Puppet raises Puppet::DataBinding::LookupError, otherwise it logs a warning and treats the file as empty. A literal 'false' document is exempted from the raise because empty YAML files can historically parse as false.
Source
Thrown at lib/puppet/functions/yaml_data.rb:31
dispatch :yaml_data do
param 'Struct[{path=>String[1]}]', :options
param 'Puppet::LookupContext', :context
end
argument_mismatch :missing_path do
param 'Hash', :options
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
- Reformat the file named in the message so the top level is a mapping (keys at column 0, list items indented under a key).
- Run 'puppet lookup <key> --explain' to see exactly which path failed.
- Sanity-check with: ruby -ryaml -e "p YAML.safe_load(File.read('file.yaml')).is_a?(Hash)".
- Tighten path/glob patterns so non-data YAML files are never matched.
Example fix
# datadir/common.yaml - before (top-level list) - ntp::servers: ['pool.ntp.org'] - profile::timezone: 'UTC' # after (top-level mapping) ntp::servers: - 'pool.ntp.org' profile::timezone: 'UTC'
Defensive patterns
Strategy: validation
Validate before calling
require 'yaml'
def valid_hiera_data?(path)
doc = YAML.safe_load(File.read(path), permitted_classes: [], aliases: false)
doc.is_a?(Hash)
rescue Psych::SyntaxError, StandardError
false
end
bad = Dir['data/**/*.yaml'].reject { |f| valid_hiera_data?(f) }
abort "top-level node is not a mapping: #{bad.join(', ')}" unless bad.empty? Try / catch
begin
Puppet::LookupContext.new.lookup('mykey')
rescue Puppet::DataBinding::LookupError => e
# message contains the offending path; fall back to a default value
Puppet.err "hiera data invalid: #{e.message}"
default_value
end Prevention
- Run a CI lint step that safe_loads every hiera YAML file and asserts Hash.
- Keep hiera datadirs dedicated to hiera data; exclude other YAML from globs.
- Treat 'puppet lookup --explain' as the first diagnostic for lookup failures.
When it happens
Trigger: hiera.yaml declares data_hash: yaml_data with path/paths/glob/mapped_paths selecting a file whose top-level node is a YAML list ('- key: value' at column 0), a bare scalar, or an empty/comments-only file; or a broad glob (e.g. 'data/*.yaml') matches a non-Hiera YAML file. The raise additionally requires Puppet[:strict] == :error and the parsed value != false.
Common situations: Writing hiera data as a top-level list instead of nesting it under a key; a truncated or half-deployed file; a glob picking up unrelated YAML (k8s manifests, docker-compose); an empty file created by a failed template render; CI passing locally but failing on a strict-mode master.
Related errors
- Unable to parse %{message}
- Function lookup() did not find a value for the name '%{name}
- Could not find data item %{key} in any Hiera data file and n
- Unrecognized value for request 'merge' parameter: '%{merge}'
- Unrecognized value for request 'merge' parameter: '#{merge}'
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/6efa0d09c9e73cd2.
Report an issue: GitHub.