puppetlabs/puppet · error · Puppet::Error

The certificate %{certname} must be cleaned from the CA firs

Error message

The certificate %{certname} must be cleaned from the CA first. To fix this,
run the following commands on the CA:
  puppetserver ca clean --certname %{certname}
  puppet ssl clean

What it means

Raised by `Puppet::Application::SSL#clean`: before deleting local files it queries the CA with `route.get_certificate(certname)`. If the CA still returns a certificate (any response other than 404), local cleaning is aborted because the CA would keep serving the old identity and the host would immediately get its stale certificate back. Note that connect failures raise a different 'Failed to connect' error, so this error specifically means the certificate is still present on the CA.

Source

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

  def clean(certname)
    # make sure cert has been removed from the CA
    if certname == Puppet[:ca_server]
      cert = nil

      begin
        ssl_context = @machine.ensure_ca_certificates
        route = create_route(ssl_context)
        _, cert = route.get_certificate(certname, ssl_context: ssl_context)
      rescue Puppet::HTTP::ResponseError => e
        if e.response.code.to_i != 404
          raise Puppet::Error.new(_("Failed to connect to the CA to determine if certificate %{certname} has been cleaned") % { certname: certname }, e)
        end
      rescue => e
        raise Puppet::Error.new(_("Failed to connect to the CA to determine if certificate %{certname} has been cleaned") % { certname: certname }, e)
      end

      if cert
        raise Puppet::Error, _(<<~END) % { certname: certname }
          The certificate %{certname} must be cleaned from the CA first. To fix this,
          run the following commands on the CA:
            puppetserver ca clean --certname %{certname}
            puppet ssl clean
        END
      end
    end

    paths = {
      'private key' => Puppet[:hostprivkey],
      'public key' => Puppet[:hostpubkey],
      'certificate request' => Puppet[:hostcsr],
      'certificate' => Puppet[:hostcert],
      'private key password file' => Puppet[:passfile]
    }
    if options[:localca]
      paths['local CA certificate'] = Puppet[:localcacert]
      paths['local CRL'] = Puppet[:hostcrl]

View on GitHub (pinned to e227c27540)

Solutions

  1. On the CA host: `puppetserver ca clean --certname <certname>` (removes the cert, CSR, and serial)
  2. Then on the agent: `puppet ssl clean` — get_certificate now 404s and local files are removed
  3. Re-run `puppet ssl bootstrap` to request a fresh certificate
  4. If you cannot use the CA CLI, clean via the CA API and wait for it to take effect before retrying

Example fix

# before (agent only)
puppet ssl clean
# => The certificate node1 must be cleaned from the CA first...
# after
# (on the CA host)
puppetserver ca clean --certname node1.example.com
# (on the agent)
puppet ssl clean && puppet ssl bootstrap
Defensive patterns

Strategy: try-catch

Validate before calling

# verify the CA no longer has the cert (404) before cleaning locally
session = Puppet.lookup(:http_session)
ssl_context = machine.ensure_ca_certificates
route = session.route_to(:puppet)
begin
  _ignored, cert = route.get_certificate(certname, ssl_context: ssl_context)
  abort 'CA still serves the certificate; run puppetserver ca clean first' if cert
rescue Puppet::HTTP::ResponseError => e
  raise unless e.response.code.to_i == 404  # 404 = safe to clean
end

Try / catch

begin
  Puppet::Application[:ssl].run unless ARGV.empty?
rescue Puppet::Error => e
  if e.message.include?('must be cleaned from the CA first')
    # orchestrate: clean on CA, then retry the local clean once
    run_on_ca('puppetserver ca clean --certname', certname)
    retry
  end
  raise
end

Prevention

When it happens

Trigger: Running `puppet ssl clean` while the CA still has a signed certificate for the certname; the rescue clauses let a 404 pass through (cert already cleaned) and turn non-404 HTTP errors into the connect-failure error instead.

Common situations: Rotating a compromised or mis-keyed host where the operator wiped the local ssl dir but forgot the CA; rebuilding a node with the same certname; decommission/recommission flows that skip the CA step.

Understand the failure class

Related errors


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