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
- Read the %{detail}: Psych::SyntaxError points to the line/column; unknown class/alias messages tell you the safe-load rule that fired
- Delete or quarantine the damaged file so find() returns nil (ENOENT path) and the object is rebuilt from its source
- If the file must be preserved, load it permissively in a separate ruby process, sanitize (drop aliases, stringify symbols), and re-dump
- 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
- Never hand-edit yaml files under vardir; regenerate them through Puppet
- After Puppet upgrades, proactively re-save or purge serialized state files
- Monitor disk space where reports/state are written to avoid truncated files
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
- Unable to parse %{message}
- Could not load external node results for %{name}: %{detail}
- You can only save objects that respond to :name
- Could not intern from %{format}: %{err}
- Could not intern_multiple from %{format}: %{err}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/84ae81202fd41009.
Report an issue: GitHub.