puppetlabs/puppet · error · Puppet::Network::HTTP::Error::HTTPBadRequestError

No request key specified in %{uri}

Error message

No request key specified in %{uri}

What it means

The indirection key is the path segment(s) after the indirection name in the URI: the certname for catalog/facts/report endpoints, the file path for file endpoints. If it is missing or empty (trailing-slash URL, blank variable), the handler raises HTTP 400 'No request key specified in <uri>', echoing the URI back to identify the malformed call.

Source

Thrown at lib/puppet/network/http/api/indirected_routes.rb:106

    unless Puppet::Node::Environment.valid_name?(environment)
      raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("The environment must be purely alphanumeric, not '%{environment}'") % { environment: environment }
    end

    configured_environment = Puppet.lookup(:environments).get(environment)
    unless configured_environment.nil?
      configured_environment = configured_environment.override_from_commandline(Puppet.settings)
      params[:environment] = configured_environment
    end

    if configured_environment.nil? && indirection.terminus.require_environment?
      raise Puppet::Network::HTTP::Error::HTTPNotFoundError, _("Could not find environment '%{environment}'") % { environment: environment }
    end

    params.delete(:bucket_path)

    if key == "" or key.nil?
      raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("No request key specified in %{uri}") % { uri: uri }
    end

    [indirection, method, key, params]
  end

  private

  # Execute our find.
  def do_find(indirection, key, params, request, response)
    result = indirection.find(key, params)
    unless result
      raise Puppet::Network::HTTP::Error::HTTPNotFoundError.new(_("Could not find %{value0} %{key}") % { value0: indirection.name, key: key }, Puppet::Network::HTTP::Issues::RESOURCE_NOT_FOUND)
    end

    rendered_result = result

    rendered_format = first_response_formatter_for(indirection.model, request, key) do |format|
      if result.respond_to?(:render)

View on GitHub (pinned to e227c27540)

Solutions

  1. Append the key: the node name for catalog/facts/reports, the module path for file endpoints
  2. Guard URL builders so they fail early when the key variable is nil or empty instead of emitting a broken URL
  3. Check path rewriting so the segment after the indirection name is not dropped
  4. URL-encode keys containing special characters so they are not parsed away

Example fix

# before
curl "https://puppet:8140/puppet/v3/catalog/?environment=production"

# after
curl "https://puppet:8140/puppet/v3/catalog/mynode.example.com?environment=production"
Defensive patterns

Strategy: validation

Validate before calling

def indirected_uri(indirection, key, environment)
  raise ArgumentError, 'request key required' if key.nil? || key.to_s.empty?
  "/puppet/v3/#{indirection}/#{URI.encode_www_form_component(key)}?environment=#{environment}"
end

Prevention

When it happens

Trigger: GET /puppet/v3/catalog/ with no node name; PUT /puppet/v3/report/ with nothing after the indirection; GET /puppet/v3/file_content/files/ with nothing after the mount; URLs where the key segment was lost to encoding, rewriting or an empty interpolation.

Common situations: Templated URL builders that leave the key blank when a variable is nil; manual curl tests ending in a trailing slash; proxies stripping path segments; scripts iterating an empty list of node names.

Related errors


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