puppetlabs/puppet · error · Puppet::Error

Could not parse YAML data for %{indirection} %{request}: %{d

Error message

Could not parse YAML data for %{indirection} %{request}: %{detail}

What it means

The YAML terminus's find() first checks the file exists, then loads it with Puppet::Util::Yaml.safe_load; a Puppet::Util::Yaml::YamlLoadError (Psych syntax errors, unpermitted classes/aliases under safe loading) is re-raised as Puppet::Error with the indirection, key, and detail. The stored YAML for the given key is present but unreadable by the current Psych/safe-load rules.

Source

Thrown at lib/puppet/indirector/yaml.rb:16

# frozen_string_literal: true

require_relative '../../puppet/indirector/terminus'
require_relative '../../puppet/util/yaml'

# The base class for YAML indirection termini.
class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
  # Read a given name's file in and convert it from YAML.
  def find(request)
    file = path(request.key)
    return nil unless Puppet::FileSystem.exist?(file)

    begin
      load_file(file)
    rescue Puppet::Util::Yaml::YamlLoadError => detail
      raise Puppet::Error, _("Could not parse YAML data for %{indirection} %{request}: %{detail}") % { indirection: indirection.name, request: request.key, detail: detail }, detail.backtrace
    end
  end

  # Convert our object to YAML and store it to the disk.
  def save(request)
    raise ArgumentError, _("You can only save objects that respond to :name") unless request.instance.respond_to?(:name)

    file = path(request.key)

    basedir = File.dirname(file)

    # This is quite likely a bad idea, since we're not managing ownership or modes.
    Dir.mkdir(basedir) unless Puppet::FileSystem.exist?(basedir)

    begin
      Puppet::Util::Yaml.dump(request.instance, file)
    rescue TypeError => detail
      Puppet.err _("Could not save %{indirection} %{request}: %{detail}") % { indirection: name, request: request.key, detail: detail }

View on GitHub (pinned to e227c27540)

Solutions

  1. Read the %{detail}: Psych::SyntaxError points to the line/column; unknown class/alias messages tell you the safe-load rule that fired
  2. Delete or quarantine the damaged file so find() returns nil (ENOENT path) and the object is rebuilt from its source
  3. If the file must be preserved, load it permissively in a separate ruby process, sanitize (drop aliases, stringify symbols), and re-dump
  4. After Puppet upgrades, expect stricter permitted-class lists; pre-convert old serialized data rather than keeping old formats in place

Example fix

# before
# Error: Could not parse YAML data for facts web01: Psych::DisallowedClass:
#        Tried to load unspecified class: Date

# after: sanitize the stored file once, then re-save
ruby -ryaml -e '
  d = YAML.unsafe_load_file("/var/cache/puppet/yaml/facts/web01.yaml")
  d.values.each { |k,v| d.values[k] = v.to_s if v.is_a?(Date) }
  YAML.safe_dump(d, File.open("/var/cache/puppet/yaml/facts/web01.yaml","w"), permitted_classes: [Symbol])
'
puppet agent -t
Defensive patterns

Strategy: try-catch

Validate before calling

file = File.join(base_dir, "#{key}.yaml")
if Puppet::FileSystem.exist?(file)
  begin
    Puppet::Util::Yaml.safe_load_file(file)
  rescue Puppet::Util::Yaml::YamlLoadError => e
    Puppet.warning "refusing request: #{file} is not safely loadable: #{e.message}"
  end
end

Try / catch

begin
  facts = Puppet::Node::Facts.indirection.find(certname)
rescue Puppet::Error => e
  raise unless e.message.start_with?('Could not parse YAML data')
  File.delete(File.join(dir, "#{certname}.yaml")) rescue nil
  facts = nil  # caller falls back to fresh fact collection
end

Prevention

When it happens

Trigger: Calling find on a yaml-backed indirection (default facts/node/report stores) when the .yaml file is truncated, hand-edited, contains aliases, or contains classes not in the permitted list for the running Puppet version (e.g., data serialized by an older Puppet with symbols or date objects now rejected).

Common situations: vardir restored from backup with damaged yaml files; version upgrades tightening safe_load permitted classes; operators hand-editing cache/state yaml; disk-full truncating report writes.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/84ae81202fd41009. Report an issue: GitHub.