{"record":{"id":"6efa0d09c9e73cd2","repo":"puppetlabs/puppet","slug":"path-file-does-not-contain-a-valid-yaml-hash-6efa0d","errorCode":null,"errorMessage":"%{path}: file does not contain a valid yaml hash","messagePattern":"%(.+?): file does not contain a valid yaml hash","errorType":"exception","errorClass":"Puppet::DataBinding::LookupError","httpStatus":null,"severity":"error","filePath":"lib/puppet/functions/yaml_data.rb","lineNumber":31,"sourceCode":"  dispatch :yaml_data do\n    param 'Struct[{path=>String[1]}]', :options\n    param 'Puppet::LookupContext', :context\n  end\n\n  argument_mismatch :missing_path do\n    param 'Hash', :options\n    param 'Puppet::LookupContext', :context\n  end\n\n  def yaml_data(options, context)\n    path = options['path']\n    context.cached_file_data(path) do |content|\n      data = Puppet::Util::Yaml.safe_load(content, [Symbol], path)\n      if data.is_a?(Hash)\n        Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data)\n      else\n        msg = _(\"%{path}: file does not contain a valid yaml hash\" % { path: path })\n        raise Puppet::DataBinding::LookupError, msg if Puppet[:strict] == :error && data != false\n\n        Puppet.warning(msg)\n        {}\n      end\n    rescue Puppet::Util::Yaml::YamlLoadError => ex\n      # YamlLoadErrors include the absolute path to the file, so no need to add that\n      raise Puppet::DataBinding::LookupError, _(\"Unable to parse %{message}\") % { message: ex.message }\n    end\n  end\n\n  def missing_path(options, context)\n    \"one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function\"\n  end\nend\n","sourceCodeStart":13,"sourceCodeEnd":46,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/functions/yaml_data.rb#L13-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# datadir/common.yaml - before (top-level list)\n- ntp::servers: ['pool.ntp.org']\n- profile::timezone: 'UTC'\n\n# after (top-level mapping)\nntp::servers:\n  - 'pool.ntp.org'\nprofile::timezone: 'UTC'","handlingStrategy":"validation","validationCode":"require 'yaml'\n\ndef valid_hiera_data?(path)\n  doc = YAML.safe_load(File.read(path), permitted_classes: [], aliases: false)\n  doc.is_a?(Hash)\nrescue Psych::SyntaxError, StandardError\n  false\nend\n\nbad = Dir['data/**/*.yaml'].reject { |f| valid_hiera_data?(f) }\nabort \"top-level node is not a mapping: #{bad.join(', ')}\" unless bad.empty?","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::LookupContext.new.lookup('mykey')\nrescue Puppet::DataBinding::LookupError => e\n  # message contains the offending path; fall back to a default value\n  Puppet.err \"hiera data invalid: #{e.message}\"\n  default_value\nend","preventionTips":["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."],"tags":["puppet","hiera","yaml","data-binding","lookup"],"backgroundTag":"invalid-yaml-structure","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}