puppetlabs/puppet · error · ArgumentError
Unsupported facts format
Error message
Unsupported facts format
What it means
convert_wire_facts in the catalog compiler only understands two wire formats for client-submitted facts: 'pson' (legacy, still accepted from older agents) and 'application/json' (the current agent format; the payload is URI-unescaped then parsed). Any other value for request.options[:facts_format] raises ArgumentError.
Source
Thrown at lib/puppet/indirector/catalog/compiler.rb:128
false
end
private
# @param facts [String] facts in a wire format for decoding
# @param format [String] a content-type string
# @return [Puppet::Node::Facts] facts object deserialized from supplied string
# @api private
def convert_wire_facts(facts, format)
case format
when 'pson'
# We unescape here because the corresponding code in Puppet::Configurer::FactHandler encodes with Puppet::Util.uri_query_encode
# PSON is deprecated, but continue to accept from older agents
Puppet::Node::Facts.convert_from('pson', CGI.unescape(facts))
when 'application/json'
Puppet::Node::Facts.convert_from('json', CGI.unescape(facts))
else
raise ArgumentError, _("Unsupported facts format")
end
end
# Add any extra data necessary to the node.
def add_node_data(node)
# Merge in our server-side facts, so they can be used during compilation.
node.add_server_facts(@server_facts)
end
# Determine which checksum to use; if agent_checksum_type is not nil,
# use the first entry in it that is also in known_checksum_types.
# If no match is found, return nil.
def common_checksum_type(agent_checksum_type)
if agent_checksum_type
agent_checksum_types = agent_checksum_type.split('.').map(&:to_sym)
checksum_type = agent_checksum_types.drop_while do |type|
!known_checksum_types.include? type
end.firstView on GitHub (pinned to e227c27540)
Solutions
- Use exactly 'application/json' (modern) or 'pson' (legacy interop) as the facts_format value
- Strip charset/parameters from content types before putting them into options
- Send no facts at all if the compile does not depend on them
Example fix
# before (ruby)
opts = { facts: facts_json, facts_format: 'json' } # => ArgumentError
# after
opts = { facts: facts_json, facts_format: 'application/json' } Defensive patterns
Strategy: validation
Validate before calling
# ruby
ALLOWED = %w[pson application/json].freeze
fmt = fmt.split(';').first.to_s.strip.downcase
raise ArgumentError, "unsupported facts format #{fmt}" unless ALLOWED.include?(fmt)
opts[:facts_format] = fmt Type guard
def supported_facts_format?(f) %w[pson application/json].include?(f) end
Try / catch
begin
Puppet::Resource::Catalog.indirection.find(key, opts)
rescue ArgumentError => e
raise unless e.message.include?('facts format')
opts[:facts_format] = 'application/json'
retry
end Prevention
- Use exactly 'application/json' for new code; keep 'pson' only for pre-4.0 interop
- Sanitize content types (strip parameters) before putting them into options
- Centralize the format constant instead of repeating the literal
When it happens
Trigger: Passing facts_format: 'json' (bare subtype), 'yaml', or a content type with parameters like 'application/json; charset=utf-8' — the value is matched literally against the two accepted strings.
Common situations: Custom clients abbreviating the MIME type to 'json'; tooling copied from the v3 REST API that used format extensions like .pson or .yaml; content-type strings copied straight from HTTP headers.
Related errors
- Facts but no fact format provided for %{request}
- Catalog for %{request} was requested with fact definition fo
- Could not mime to %{format}: %{err}
- #{path}: #{detail.message}
- Could not deserialize catalog from %{format}: %{detail}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/e3179073b4e3cec9.
Report an issue: GitHub.