puppetlabs/puppet · error · Puppet::Error
Find %{uri} resulted in 404 with the message: %{body}
Error message
Find %{uri} resulted in 404 with the message: %{body} What it means
The facts REST terminus maps a server 404 on a facts GET to nil (fact set not found) unless the request carried options[:fail_on_404], in which case it raises Puppet::Error embedding the request path and the server's response body. Same contract as the catalog REST terminus: find returns nil for missing data unless the caller explicitly demands failure.
Source
Thrown at lib/puppet/indirector/facts/rest.rb:23
class Puppet::Node::Facts::Rest < Puppet::Indirector::REST
desc "Find and save facts about nodes over HTTP via REST."
def find(request)
session = Puppet.lookup(:http_session)
api = session.route_to(:puppet)
_, facts = api.get_facts(
request.key,
environment: request.environment.to_s
)
facts
rescue Puppet::HTTP::ResponseError => e
if e.response.code == 404
return nil unless request.options[:fail_on_404]
_, body = parse_response(e.response)
msg = _("Find %{uri} resulted in 404 with the message: %{body}") % { uri: elide(e.response.url.path, 100), body: body }
raise Puppet::Error, msg
else
raise convert_to_http_error(e.response)
end
end
def save(request)
raise ArgumentError, _("PUT does not accept options") unless request.options.empty?
session = Puppet.lookup(:http_session)
api = session.route_to(:puppet)
api.put_facts(
request.key,
facts: request.instance,
environment: request.environment.to_s
)
# preserve existing behavior
nilView on GitHub (pinned to e227c27540)
Solutions
- Drop fail_on_404 and treat nil as 'no facts on this server' for discovery or inventory use cases
- If facts should exist, verify server-side (puppet facts find or a PuppetDB query) and re-submit by running the agent on the node
- Check the response body in the message — it distinguishes unknown-node 404s from unknown-route 404s
Example fix
# before (ruby) facts = Puppet::Node::Facts.indirection.find(name, fail_on_404: true) # 404 => Puppet::Error # after facts = Puppet::Node::Facts.indirection.find(name) # 404 => nil puts 'no facts stored' unless facts
Defensive patterns
Strategy: try-catch
Validate before calling
# ruby facts = Puppet::Node::Facts.indirection.find(name) # default nil semantics return :no_facts if facts.nil?
Type guard
def facts_stored?(name) !Puppet::Node::Facts.indirection.find(name).nil? end
Try / catch
begin
Puppet::Node::Facts.indirection.find(name, fail_on_404: true)
rescue Puppet::Error => e
raise unless e.message.include?('404')
nil # treat as absent and report
end Prevention
- Use fail_on_404 only where a missing fact set must abort the workflow
- Distinguish 404 body types (unknown node vs unknown route) before escalating
- For fleet inventory, query PuppetDB instead of the facts indirection
When it happens
Trigger: Puppet::Node::Facts.indirection.find(name, fail_on_404: true) against a server that answers 404 — facts were never stored, were cleaned, or the request hit a server without that node's facts.
Common situations: Inventory scripts probing facts for decommissioned or never-registered nodes; facts cleaned on the master or purged from PuppetDB; a load balancer routing the GET to a server whose fact store does not contain the node.
Related errors
- Find %{uri} resulted in 404 with the message: %{body}
- PUT does not accept options
- Facts but no fact format provided for %{request}
- Catalog environment didn't stabilize after %{tries} fetches,
- Environment '%{environment}' not found on server, aborting r
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/3df3ce6dae7756f8.
Report an issue: GitHub.