puppetlabs/puppet · error · Puppet::Error

Could not parse MessagePack data for %{indirection} %{key}:

Error message

Could not parse MessagePack data for %{indirection} %{key}: %{detail}

What it means

Raised by the MessagePack terminus when the cache file was read successfully but model.convert_from('msgpack', data) fails during deserialization. It means the bytes on disk are not valid MessagePack for the model: a truncated file (agent killed mid-write), a file written by a different serializer (YAML or JSON content renamed/dropped into a .msgpack path), or data serialized by an incompatible msgpack gem version.

Source

Thrown at lib/puppet/indirector/msgpack.rb:76

  private

  def load_msgpack_from_file(file, key)
    msgpack = nil

    begin
      msgpack = Puppet::FileSystem.read(file, :encoding => 'utf-8')
    rescue Errno::ENOENT
      return nil
    rescue => detail
      # TRANSLATORS "MessagePack" is a program name and should not be translated
      raise Puppet::Error, _("Could not read MessagePack data for %{indirection} %{key}: %{detail}") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace
    end

    begin
      from_msgpack(msgpack)
    rescue => detail
      raise Puppet::Error, _("Could not parse MessagePack data for %{indirection} %{key}: %{detail}") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace
    end
  end

  def from_msgpack(text)
    model.convert_from('msgpack', text)
  end

  def to_msgpack(object)
    object.render('msgpack')
  end
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Delete the offending cache file named in the error (rm <vardir>/<indirection>/<key>.msgpack); the next find will rebuild it
  2. Clear the whole cache directory if multiple entries are affected: find $(puppet config print vardir) -name '*.msgpack' -delete
  3. If you recently changed cache_terminus, purge stale files written by the previous format before relying on the new terminus
  4. Verify the msgpack gem version matches across agents/servers (gem list msgpack) when caches are shared
  5. Check for disk-full (df -h) or OOM kills in dmesg if corruption recurs, since those truncate writes

Example fix

# before
# Error: Could not parse MessagePack data for catalog web01: unexpected token...

# after: purge the corrupt cache and re-fetch
rm -f "$(puppet config print vardir)/catalog/$(puppet config print certname).msgpack"
puppet agent -t   # recompiles and re-caches cleanly
Defensive patterns

Strategy: fallback

Validate before calling

file = File.join(Puppet[:vardir].to_s, indirection_name, "#{key}.msgpack")
if Puppet::FileSystem.exist?(file)
  data = Puppet::FileSystem.read(file, encoding: 'utf-8') rescue nil
  return unless data
  require 'msgpack'
  begin; MessagePack.unpack(data); rescue => e; Puppet.warning "stale cache, removing"; File.delete(file); end
end

Try / catch

begin
  catalog = Puppet::Resource::Catalog.indirection.find(key)
rescue Puppet::Error => e
  raise unless e.message.start_with?('Could not parse MessagePack data')
  File.delete(File.join(Puppet[:vardir].to_s, 'catalog', "#{key}.msgpack")) rescue nil
  catalog = nil  # force full compile path
end

Prevention

When it happens

Trigger: Calling find on an indirection whose terminus is msgpack (cache_terminus = msgpack) when the .msgpack file is corrupt: e.g., the process was OOM-killed while Puppet::FileSystem.replace_file was writing, an operator hand-edited the cache file, or a YAML cache file from a prior terminus setting was left in place after switching to msgpack.

Common situations: Switching catalog cache_terminus from yaml/json to msgpack without clearing the old cache directory; disk-full conditions that truncated writes; restoring vardir from a backup made with a different serialization setting; msgpack gem major-version upgrades that change symbol/string handling.

Related errors


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