oven-sh/bun · error · CertError
UNABLE_TO_GET_CRL
Error message
UNABLE_TO_GET_CRL
What it means
X509 verify result 3 (X509_V_ERR_UNABLE_TO_GET_CRL): certificate-chain validation was configured to check revocation via CRLs, and no Certificate Revocation List could be found for a certificate in the chain. Bun translates the BoringSSL verify code through get_cert_error_from_no (src/http/lib.rs:1522) into CertError::UNABLE_TO_GET_CRL, rejecting the TLS handshake with message "unable to get certificate CRL" (FetchTasklet.rs:1379).
Source
Thrown at src/http/error.rs:127
Sys(#[from] bun_errno::SystemErrno),
#[error(transparent)]
Zlib(bun_zlib::ZlibError),
#[error(transparent)]
Brotli(bun_brotli::Error),
#[error(transparent)]
Zstd(bun_zstd::ZstdError),
#[error(transparent)]
Picohttp(bun_picohttp::ParseResponseError),
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, strum::IntoStaticStr)]
pub enum CertError {
#[error("OK")]
OK,
#[error("UNABLE_TO_GET_ISSUER_CERT")]
UNABLE_TO_GET_ISSUER_CERT,
#[error("UNABLE_TO_GET_CRL")]
UNABLE_TO_GET_CRL,
#[error("UNABLE_TO_DECRYPT_CERT_SIGNATURE")]
UNABLE_TO_DECRYPT_CERT_SIGNATURE,
#[error("UNABLE_TO_DECRYPT_CRL_SIGNATURE")]
UNABLE_TO_DECRYPT_CRL_SIGNATURE,
#[error("UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY")]
UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
#[error("CERT_SIGNATURE_FAILURE")]
CERT_SIGNATURE_FAILURE,
#[error("CRL_SIGNATURE_FAILURE")]
CRL_SIGNATURE_FAILURE,
#[error("CERT_NOT_YET_VALID")]
CERT_NOT_YET_VALID,
#[error("CERT_HAS_EXPIRED")]
CERT_HAS_EXPIRED,
#[error("CRL_NOT_YET_VALID")]
CRL_NOT_YET_VALID,
#[error("CRL_HAS_EXPIRED")]View on GitHub (pinned to 8c5296ac45)
Solutions
- Publish and host the CA's CRL at the cRLDistributionPoint URL embedded in the certificate and make sure it is reachable
- Disable mandatory CRL checking on the client for that host (rely on OCSP or the CA's assurance) — Bun's default fetch does not require CRLs, so remove any custom checkServerIdentity/verify setup that enables it
- Switch the PKI to OCSP-based revocation so no CRL lookup is needed
- For internal CAs where revocation is handled operationally, add the CA to the trust list so leaf checks short-circuit before CRL lookup
Defensive patterns
Strategy: try-catch
Type guard
function isCertErrorCode(e: unknown, code = "UNABLE_TO_GET_CRL"): e is Error & { code: string } {
return e instanceof Error && (e as any).code === code;
} Try / catch
try {
await fetch(url);
} catch (e) {
if (isCertErrorCode(e, "UNABLE_TO_GET_CRL")) {
// CRL infrastructure problem — escalate to the PKI team rather than bypassing
throw new Error("Revocation (CRL) unavailable for peer certificate");
}
throw e;
} Prevention
- Prefer OCSP-capable CAs so clients never need CRL fetches
- Keep cRLDistributionPoint URLs reachable and monitored if your PKI uses CRLs
- Don't enable strict CRL revocation on clients unless the PKI actually publishes CRLs
When it happens
Trigger: A TLS connection (fetch/https/Bun.connect, including proxied CONNECT tunnels) where CRL-based revocation checking is active and the CA publishes no (or an unreachable) CRL for the cert. Rare with Bun's default configuration, which does not require CRLs.
Common situations: Internal PKIs with CRL checking enabled but no CRL distribution points hosted, a CRL URL that is down/unreachable (the verifier treats it as missing), or hardened environments that turn on strict revocation checking.
Related errors
- UNABLE_TO_DECRYPT_CRL_SIGNATURE
- CRL_SIGNATURE_FAILURE
- CRL_HAS_EXPIRED
- CRL_NOT_YET_VALID
- ERROR_IN_CRL_LAST_UPDATE_FIELD
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/6db38542918c32f3.
Report an issue: GitHub.