puppetlabs/puppet · error · Puppet::Error
Catalog for %{request} was requested with fact definition fo
Error message
Catalog for %{request} was requested with fact definition for the wrong node (%{fact_name}). What it means
After deserializing the facts sent with a catalog request, the compiler verifies facts.name equals request.key (the node whose catalog was requested). A mismatch raises Puppet::Error because compiling a node's catalog against another node's facts would produce a silently wrong catalog (hostname/IP-dependent resources would be wrong).
Source
Thrown at lib/puppet/indirector/catalog/compiler.rb:38
# @param request [Puppet::Indirector::Request] an indirection request
# (possibly) containing facts
# @return [Puppet::Node::Facts] facts object corresponding to facts in request
def extract_facts_from_request(request)
text_facts = request.options[:facts]
return unless text_facts
format = request.options[:facts_format]
unless format
raise ArgumentError, _("Facts but no fact format provided for %{request}") % { request: request.key }
end
Puppet::Util::Profiler.profile(_("Found facts"), [:compiler, :find_facts]) do
facts = text_facts.is_a?(Puppet::Node::Facts) ? text_facts :
convert_wire_facts(text_facts, format)
unless facts.name == request.key
raise Puppet::Error, _("Catalog for %{request} was requested with fact definition for the wrong node (%{fact_name}).") % { request: request.key.inspect, fact_name: facts.name.inspect }
end
return facts
end
end
def save_facts_from_request(facts, request)
Puppet::Node::Facts.indirection.save(facts, nil,
:environment => request.environment,
:transaction_uuid => request.options[:transaction_uuid])
end
# Compile a node's catalog.
def find(request)
facts = extract_facts_from_request(request)
save_facts_from_request(facts, request) unless facts.nil?
View on GitHub (pinned to e227c27540)
Solutions
- Make the facts name match the request: set facts.name = request.key (or fix the certname fact) before serializing
- Generate per-node facts fixtures in tests instead of sharing one
- On agents, clear stale fact caches and stop custom facts from shadowing certname
Example fix
# before (ruby)
facts = Puppet::Node::Facts.new('nodeB', values)
Puppet::Resource::Catalog.indirection.find('nodeA',
facts: facts.to_pson, facts_format: 'pson') # => Puppet::Error: wrong node
# after
facts.name = 'nodeA'
Puppet::Resource::Catalog.indirection.find('nodeA',
facts: facts.to_pson, facts_format: 'pson') Defensive patterns
Strategy: validation
Validate before calling
# ruby facts.name = request_key if facts.respond_to?(:name=) raise ArgumentError, 'facts belong to another node' unless facts.name == request_key
Type guard
def facts_match_node?(facts, key) facts.nil? || facts.name == key end
Try / catch
begin
Puppet::Resource::Catalog.indirection.find(key, opts)
rescue Puppet::Error => e
raise unless e.message.include?('wrong node')
facts.name = key
opts[:facts] = facts.to_pson
retry
end Prevention
- Set the facts object name to the request key before serializing, every time
- Never share facts fixtures across nodes in tests; generate them per certname
- Keep custom facts from overwriting certname on agents
When it happens
Trigger: Requesting a catalog for nodeA with a facts payload whose name field is nodeB — e.g. find('nodeA', facts: facts_for_nodeB_serialized, facts_format: 'pson'); a facts object reused across nodes in a test harness.
Common situations: certname in puppet.conf set to one FQDN while a custom fact or stale fact cache reports a different hostname; monitoring or compile-testing tools that fetch facts once and request catalogs for many nodes; facts from a golden image reporting the image's original hostname.
Related errors
- Catalog environment didn't stabilize after %{tries} fetches,
- Facts but no fact format provided for %{request}
- Unsupported facts format
- Could not find node '%{name}'; cannot compile
- Unable to verify the SSL certificate at %{uri}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/1dc2a639798ac11a.
Report an issue: GitHub.