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 catalog REST terminus turns a server 404 into a Puppet::Error whose message embeds the request path and the server's response body — but only when the request carried options[:fail_on_404] truthy; otherwise a 404 maps to nil (catalog not found). This preserves the indirector convention that find returns nil for missing resources while letting agent runs fail loudly on a missing catalog.

Source

Thrown at lib/puppet/indirector/catalog/rest.rb:46

    _, catalog = api.post_catalog(
      request.key,
      facts: request.options[:facts_for_catalog],
      environment: request.environment.to_s,
      configured_environment: request.options[:configured_environment],
      check_environment: request.options[:check_environment],
      transaction_uuid: request.options[:transaction_uuid],
      job_uuid: request.options[:job_id],
      static_catalog: request.options[:static_catalog],
      checksum_type: checksum_type
    )
    catalog
  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
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Read the body in the message — puppetserver's 404 body states what was not found (node vs environment); fix that on the server side
  2. Verify the agent's environment setting and that the environment exists on the master before failing hard
  3. If nil-not-found semantics are wanted (tooling), call find without fail_on_404

Example fix

# before (ruby)
catalog = Puppet::Resource::Catalog.indirection.find(name,
  fail_on_404: true)  # 404 => Puppet::Error

# after: tolerate missing catalogs
catalog = Puppet::Resource::Catalog.indirection.find(name)  # 404 => nil
Defensive patterns

Strategy: try-catch

Validate before calling

# ruby
# choose semantics before the call; only pass fail_on_404 when missing is fatal
catalog = Puppet::Resource::Catalog.indirection.find(name)
raise 'catalog missing' if catalog.nil? && strict

Type guard

def catalog_present?(name)
  !Puppet::Resource::Catalog.indirection.find(name).nil?
end

Try / catch

begin
  Puppet::Resource::Catalog.indirection.find(name, fail_on_404: true)
rescue Puppet::Error => e
  raise unless e.message.include?('404')
  nil  # or retry against the primary master if routed to a compile server
end

Prevention

When it happens

Trigger: Puppet::Resource::Catalog.indirection.find(name, fail_on_404: true) against a server that answers 404 (unknown node, unknown environment, or a request routed to a server without the node's data); agent runs, which set fail_on_404 so a missing catalog aborts instead of silently returning nil.

Common situations: The requested environment does not exist on the master (common after environment renames); a load balancer or SRV routing sending the catalog GET to a compile server that does not know the node; agents pointing at a compile-masters tier during migration.

Related errors


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