{"record":{"id":"355f176255b5db4a","repo":"puppetlabs/puppet","slug":"the-private-key-is-missing-from-path","errorCode":null,"errorMessage":"The private key is missing from '%{path}'","messagePattern":"The private key is missing from '%(.+?)'","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/x509/cert_provider.rb","lineNumber":216,"sourceCode":"\n  # Load a private key from the configured `privatekeydir`. For\n  # historical reasons, names are case-insensitive.\n  #\n  # @param name [String] The private key identity\n  # @param required [Boolean] If true, raise if it is missing\n  # @param password [String, nil] If the private key is encrypted, decrypt\n  #   it using the password. If the key is encrypted, but a password is\n  #   not specified, then the key cannot be loaded.\n  # @return (see #load_private_key_from_pem)\n  # @raise (see #load_private_key_from_pem)\n  # @raise [Puppet::Error] if the private key cannot be loaded\n  #\n  # @api private\n  def load_private_key(name, required: false, password: nil)\n    path = @hostprivkey || to_path(@privatekeydir, name)\n    pem = load_pem(path)\n    if !pem && required\n      raise Puppet::Error, _(\"The private key is missing from '%{path}'\") % { path: path }\n    end\n\n    pem ? load_private_key_from_pem(pem, password: password) : nil\n  rescue SystemCallError => e\n    raise Puppet::Error.new(_(\"Failed to load private key for '%{name}'\") % { name: name }, e)\n  end\n\n  # Load a PEM encoded private key.\n  #\n  # @param pem [String] PEM encoded private key\n  # @param password [String, nil] If the private key is encrypted, decrypt\n  #   it using the password. If the key is encrypted, but a password is\n  #   not specified, then the key cannot be loaded.\n  # @return [OpenSSL::PKey::RSA, OpenSSL::PKey::EC] The private key\n  # @raise [OpenSSL::PKey::PKeyError] The `pem` text does not contain a valid key\n  #\n  # @api private\n  def load_private_key_from_pem(pem, password: nil)","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/x509/cert_provider.rb#L198-L234","documentation":"CertProvider#load_private_key raises Puppet::Error when required is true and load_pem finds nothing at @hostprivkey, or at privatekeydir/<name>.pem when hostprivkey is unset. The node expects a client identity but the private half is gone, and the signed certificate cannot be used without its key.","triggerScenarios":"SSLProvider#load_context finds a client certificate but the key file is missing; certname changed (fqdn/certname setting drift) so the key lives under a different filename in privatekeydir; key removed by rotation or cleanup scripts; file unreadable to the running user.","commonSituations":"Certificate restored from backup but the key was not (or vice versa); host renamed causing certname mismatch; ssldir mounted differently between root and the puppet user; backups that skip private_keys.","solutions":["Check `puppet config print certname hostprivkey privatekeydir` and look for <certname>.pem under privatekeydir","If certname drifted, set certname back to the enrolled name or move/rename the key file to match","Restore the key from backup with 0600 permissions and correct ownership","If the key is lost, re-enroll: remove cert, key, and CSR files, run `puppet agent -t`, sign the new request on the CA"],"exampleFix":"# before: cert exists, key lost\n$ ls ssl/certs/agent.example.com.pem ssl/private_keys/\nssl/certs/agent.example.com.pem\n\n# after: re-enroll\n$ rm ssl/certs/agent.example.com.pem\n$ puppet agent -t    # new key + CSR; sign on CA; cert is fetched","handlingStrategy":"validation","validationCode":"key = Puppet[:hostprivkey] || File.join(Puppet[:privatekeydir], \"#{Puppet[:certname]}.pem\")\nraise \"private key missing at #{key}\" unless File.size?(key)","typeGuard":null,"tryCatchPattern":"begin\n  key = provider.load_private_key(name, required: true, password: pw)\nrescue Puppet::Error => e\n  reenroll!(name) if e.message.include?('private key is missing')\n  raise\nend","preventionTips":["Pin certname explicitly in puppet.conf so host renames cannot desync the identity","Back up private_keys with the certs (0600, correct owner) as one unit","Alert on certificates that exist without a matching key file"],"tags":["ruby","puppet","ssl","private-key","x509","enrollment"],"backgroundTag":"missing-private-key","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}