puppetlabs/puppet · error · Puppet::Error

Could not submit certificate request for '%{name}' to %{url}

Error message

Could not submit certificate request for '%{name}' to %{url} due to a conflict on the server

What it means

Raised while handling a `Puppet::HTTP::ResponseError` from `route.put_certificate_request` when the CA answers HTTP 400 to a CSR submission. In this code path a 400 means the server rejected the request as conflicting — a CSR for that certname already exists whose content (subject, DNS alt names, CSR attributes, or policy fields) differs from the newly submitted one. The local key and CSR generation succeeded; it is server-side state that blocks the request.

Source

Thrown at lib/puppet/application/ssl.rb:195

    ssl_context = @ssl_provider.load_context(certname: certname, password: password)
    puts ssl_context.client_cert.to_text
  end

  def submit_request(ssl_context)
    key = @cert_provider.load_private_key(Puppet[:certname])
    unless key
      key = create_key(Puppet[:certname])
      @cert_provider.save_private_key(Puppet[:certname], key)
    end

    csr = @cert_provider.create_request(Puppet[:certname], key)
    route = create_route(ssl_context)
    route.put_certificate_request(Puppet[:certname], csr, ssl_context: ssl_context)
    @cert_provider.save_request(Puppet[:certname], csr)
    Puppet.notice _("Submitted certificate request for '%{name}' to %{url}") % { name: Puppet[:certname], url: route.url }
  rescue Puppet::HTTP::ResponseError => e
    if e.response.code == 400
      raise Puppet::Error, _("Could not submit certificate request for '%{name}' to %{url} due to a conflict on the server") % { name: Puppet[:certname], url: route.url }
    else
      raise Puppet::Error.new(_("Failed to submit certificate request: %{message}") % { message: e.message }, e)
    end
  rescue => e
    raise Puppet::Error.new(_("Failed to submit certificate request: %{message}") % { message: e.message }, e)
  end

  def generate_request(certname)
    key = @cert_provider.load_private_key(certname)
    unless key
      key = create_key(certname)
      @cert_provider.save_private_key(certname, key)
    end

    csr = @cert_provider.create_request(certname, key)
    @cert_provider.save_request(certname, csr)
    Puppet.notice _("Generated certificate request in '%{path}'") % { path: @cert_provider.to_path(Puppet[:requestdir], certname) }
  rescue => e

View on GitHub (pinned to e227c27540)

Solutions

  1. Clean the existing request on the CA: `puppetserver ca clean --certname <certname>`, then re-run `puppet ssl bootstrap`
  2. On the agent, run `puppet ssl clean` before resubmitting so the local key/CSR state is consistent with what is sent
  3. Diff csr_attributes.yaml / dns_alt_names against what was first submitted and align them
  4. If it persists, check the CA's puppetserver log for the 400 response body, which states the exact conflict reason

Example fix

# on the CA
puppetserver ca clean --certname node1.example.com
# on the agent
puppet ssl clean
puppet ssl bootstrap
Defensive patterns

Strategy: try-catch

Try / catch

begin
  route.put_certificate_request(certname, csr, ssl_context: ssl_context)
rescue Puppet::HTTP::ResponseError => e
  raise if e.response.code != 400
  # 400 = server-side conflict with the existing CSR
  Puppet.err "CSR conflict (HTTP 400) for #{certname}: clean the cert on the CA, then resubmit"
  raise Puppet::Error, e.message, e
end

Prevention

When it happens

Trigger: The agent runs `puppet ssl submit_certificate_request` or `puppet ssl bootstrap` after regenerating its private key or editing csr_attributes.yaml/policy.json while the CA still holds the previous CSR; the branch `if e.response.code == 400` fires and re-raises as this Puppet::Error.

Common situations: Wiping /etc/puppetlabs/puppet/ssl on the agent without cleaning on the CA; changing dns_alt_names or CSR attributes between attempts; a CA signing policy that mutates CSRs; load-balanced compile masters where only some servers have the old request.

Understand the failure class

Related errors


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