puppetlabs/puppet · error · Puppet::Error

Could not deserialize catalog from %{format}: %{detail}

Error message

Could not deserialize catalog from %{format}: %{detail}

What it means

In 'puppet apply --catalog <file>' (apply.rb), the catalog text is deserialized with Puppet::Resource::Catalog.convert_from(Puppet::Resource::Catalog.default_format, text); any exception is re-raised as Puppet::Error 'Could not deserialize catalog from ...' with the original detail and backtrace preserved. The format is the catalog's default serialization, so the file must contain exactly that payload.

Source

Thrown at lib/puppet/application/apply.rb:354

  end

  def read_catalog(text)
    facts = get_facts()
    node = get_node()
    configured_environment = get_configured_environment(node)

    # TRANSLATORS "puppet apply" is a program command and should not be translated
    Puppet.override({ :current_environment => configured_environment }, _("For puppet apply")) do
      configure_node_facts(node, facts)

      # NOTE: Does not set rich_data = true automatically (which would ensure always reading catalog with rich data
      # on (seemingly the right thing to do)), but that would remove the ability to test what happens when a
      # rich catalog is processed without rich_data being turned on.
      format = Puppet::Resource::Catalog.default_format
      begin
        catalog = Puppet::Resource::Catalog.convert_from(format, text)
      rescue => detail
        raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
      end
      # Resolve all deferred values and replace them / mutate the catalog
      Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, configured_environment, Puppet[:preprocess_deferred])

      catalog.to_ral
    end
  end

  def apply_catalog(catalog)
    configurer = Puppet::Configurer.new
    configurer.run(:catalog => catalog, :pluginsync => false)
  end

  # Returns facts or nil
  #
  def get_facts
    facts = nil
    unless Puppet[:node_name_fact].empty?

View on GitHub (pinned to e227c27540)

Solutions

  1. Read the %{detail} in the message — it carries the original exception naming the exact parse/conversion failure
  2. Regenerate the catalog with a puppet version identical (or compatible) to the one running puppet apply --catalog
  3. Pre-validate the file is complete and well-formed (e.g. JSON.parse / jq) before handing it to apply
  4. Re-fetch a fresh catalog rather than editing the old one

Example fix

# before
puppet apply --catalog /tmp/catalog.json  # truncated payload -> Puppet::Error

# after
ruby -rjson -e 'JSON.parse(File.read("/tmp/catalog.json"))' && \
  puppet apply --catalog /tmp/catalog.json  # regenerate first if this fails
Defensive patterns

Strategy: try-catch

Validate before calling

require 'json'
parsed = JSON.parse(File.read(catalog_path)) # raises on truncation/syntax first
# structural sanity: resources array present
raise 'not a catalog' unless parsed['resources'] rescue raise 'not a catalog'

Try / catch

begin
  catalog = Puppet::Resource::Catalog.convert_from(fmt, text)
rescue => detail
  raise "catalog #{path} unusable (#{detail.message}); regenerate with a matching puppet version"
end

Prevention

When it happens

Trigger: Passing a truncated or hand-edited catalog file; JSON/PSON that is syntactically broken; a catalog produced by a different (usually newer) puppet whose resource serialization this version cannot convert; an effectively empty file.

Common situations: Catalog fetched on one master and applied on an agent with mismatched puppet versions; file corrupted in transfer (partial copy, encoding mangling); using --catalog with a file in the wrong format such as YAML.

Related errors


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