puppetlabs/puppet · error · OpenSSL::X509::CRLError
Failed to parse CRLs as PEM
Error message
Failed to parse CRLs as PEM
What it means
CertProvider#load_crls_from_pem raises OpenSSL::X509::CRLError when the CRL text contains no '-----BEGIN X509 CRL-----' block (CRL_DELIMITERS fails to match), and the same class surfaces from OpenSSL::X509::CRL.new for a block that is present but malformed. The CRL is unusable, so revocation checking and the SSL context fail.
Source
Thrown at lib/puppet/x509/cert_provider.rb:124
if !pem && required
raise Puppet::Error, _("The CRL is missing from '%{path}'") % { path: @crlpath }
end
pem ? load_crls_from_pem(pem) : nil
rescue SystemCallError => e
raise Puppet::Error.new(_("Failed to load CRLs from '%{crlpath}'") % { crlpath: @crlpath }, e)
end
# Load PEM encoded CRL(s).
#
# @param pem [String] PEM encoded CRL(s)
# @return [Array<OpenSSL::X509::CRL>] Array of CRLs
# @raise [OpenSSL::X509::CRLError] The `pem` text does not contain a valid CRL
#
# @api private
def load_crls_from_pem(pem)
# TRANSLATORS 'PEM' is an acronym and shouldn't be translated
raise OpenSSL::X509::CRLError, _("Failed to parse CRLs as PEM") if pem !~ CRL_DELIMITERS
pem.scan(CRL_DELIMITERS).map do |text|
OpenSSL::X509::CRL.new(text)
end
end
# Return the time when the CRL was last updated.
#
# @return [Time, nil] Time when the CRL was last updated, or nil if we don't
# have a CRL
#
# @api private
def crl_last_update
stat = Puppet::FileSystem.stat(@crlpath)
Time.at(stat.mtime)
rescue Errno::ENOENT
nil
endView on GitHub (pinned to e227c27540)
Solutions
- Inspect: `openssl crl -in crl.pem -noout -text` must show a CRL, not a certificate or garbage
- Convert DER to PEM: `openssl crl -inform der -in crl.der -outform pem -out crl.pem`
- Delete the bad file and rerun `puppet agent -t` to refetch it
- Re-publish the CRL on the CA if the published file itself is broken
Example fix
# before $ openssl crl -in crl.pem -noout unable to load CRL # after $ openssl crl -inform der -in crl.der -outform pem -out crl.pem $ openssl crl -in crl.pem -noout
Defensive patterns
Strategy: validation
Validate before calling
def pem_crl?(path) File.read(path).match?(/-----BEGIN X509 CRL-----/) end raise 'crl.pem is not PEM' unless pem_crl?(Puppet[:hostcrl])
Try / catch
begin
crls = provider.load_crls(required: true)
rescue OpenSSL::X509::CRLError => e
abort "CRL at #{Puppet[:hostcrl]} is malformed: #{e.message} — refetch with `puppet agent -t`"
end Prevention
- Publish and fetch CRLs as PEM (`openssl crl -outform pem`)
- Validate with `openssl crl -noout` in provisioning scripts before enabling revocation checking
When it happens
Trigger: crl.pem truncated by an interrupted download; DER binary saved with a .pem name; a certificate block saved into crl.pem by mistake; file corruption from disk issues or editors rewriting the file.
Common situations: Interrupted first agent run; scripts generating the CRL with `openssl crl -outform der`; config management that templates or rewrites the CRL incorrectly.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse CA certificates as PEM
- PathPatterns cannot be created with a zero byte.
- The CRL is missing from '%{path}'
- The CA certificates are missing from '%{path}'
- The private key is missing from '%{path}'
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/692cbf9971270f71.
Report an issue: GitHub.