{"record":{"id":"f7f499025cec68f5","repo":"oven-sh/bun","slug":"cert-chain-too-long","errorCode":"CERT_CHAIN_TOO_LONG","errorMessage":"CERT_CHAIN_TOO_LONG","messagePattern":"CERT_CHAIN_TOO_LONG","errorType":"error_code","errorClass":"CertError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":165,"sourceCode":"    #[error(\"ERROR_IN_CERT_NOT_BEFORE_FIELD\")]\n    ERROR_IN_CERT_NOT_BEFORE_FIELD,\n    #[error(\"ERROR_IN_CERT_NOT_AFTER_FIELD\")]\n    ERROR_IN_CERT_NOT_AFTER_FIELD,\n    #[error(\"ERROR_IN_CRL_LAST_UPDATE_FIELD\")]\n    ERROR_IN_CRL_LAST_UPDATE_FIELD,\n    #[error(\"ERROR_IN_CRL_NEXT_UPDATE_FIELD\")]\n    ERROR_IN_CRL_NEXT_UPDATE_FIELD,\n    #[error(\"OUT_OF_MEM\")]\n    OUT_OF_MEM,\n    #[error(\"DEPTH_ZERO_SELF_SIGNED_CERT\")]\n    DEPTH_ZERO_SELF_SIGNED_CERT,\n    #[error(\"SELF_SIGNED_CERT_IN_CHAIN\")]\n    SELF_SIGNED_CERT_IN_CHAIN,\n    #[error(\"UNABLE_TO_GET_ISSUER_CERT_LOCALLY\")]\n    UNABLE_TO_GET_ISSUER_CERT_LOCALLY,\n    #[error(\"UNABLE_TO_VERIFY_LEAF_SIGNATURE\")]\n    UNABLE_TO_VERIFY_LEAF_SIGNATURE,\n    #[error(\"CERT_CHAIN_TOO_LONG\")]\n    CERT_CHAIN_TOO_LONG,\n    #[error(\"CERT_REVOKED\")]\n    CERT_REVOKED,\n    #[error(\"INVALID_CA\")]\n    INVALID_CA,\n    #[error(\"PATH_LENGTH_EXCEEDED\")]\n    PATH_LENGTH_EXCEEDED,\n    #[error(\"INVALID_PURPOSE\")]\n    INVALID_PURPOSE,\n    #[error(\"CERT_UNTRUSTED\")]\n    CERT_UNTRUSTED,\n    #[error(\"CERT_REJECTED\")]\n    CERT_REJECTED,\n    #[error(\"SUBJECT_ISSUER_MISMATCH\")]\n    SUBJECT_ISSUER_MISMATCH,\n    #[error(\"AKID_SKID_MISMATCH\")]\n    AKID_SKID_MISMATCH,\n    #[error(\"AKID_ISSUER_SERIAL_MISMATCH\")]","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L147-L183","documentation":"CertError::CERT_CHAIN_TOO_LONG maps BoringSSL X509 verify code 22 (X509_V_ERR_CERT_CHAIN_TOO_LONG) via get_cert_error_from_no() in src/http/lib.rs:1541. The presented certificate chain exceeds the verifier's maximum chain depth, so verification aborts before reaching a trust anchor. JS error.code is CERT_CHAIN_TOO_LONG with message 'certificate chain too long' (FetchTasklet.rs:1434).","triggerScenarios":"Server sends more intermediates than the depth limit (commonly > ~10 in BoringSSL); a cross-signed chain plus extra bundled roots in the served chain; a loop or duplicate certs in the PEM bundle sent as the chain.","commonSituations":"fullchain.pem assembled from multiple renewal generations, legacy cross-signed paths kept 'just in case', misconfigured load balancers concatenating several chains, internal PKI with deep sub-CA hierarchies.","solutions":["Run openssl s_client -connect host:443 -showcerts and count certs; remove everything except the shortest path leaf -> intermediate(s) -> root","Drop duplicate and cross-signed alternative paths from the served chain","If operating the PKI, flatten the hierarchy (fewer intermediate CAs) so the path fits the depth limit","Verify the trimmed chain locally: openssl verify -show_chain -untrusted intermediates.pem leaf.pem"],"exampleFix":"# before: fullchain.pem has leaf + 4 intermediates + 2 cross-signed variants\ncat leaf.pem int1.pem int2.pem > /etc/ssl/fullchain.pem\n# after: shortest valid path only\ncat leaf.pem int1.pem int2.pem root-ca.pem > /etc/ssl/fullchain.pem\n# then reload nginx/haproxy and re-test\nopenssl s_client -connect example.com:443 -brief </dev/null","handlingStrategy":"validation","validationCode":"import tls from \"node:tls\";\nimport { execSync } from \"node:child_process\";\nfunction chainDepth(host: string, port = 443): number {\n  const out = execSync(`openssl s_client -connect ${host}:${port} -showcerts </dev/null 2>/dev/null`).toString();\n  return (out.match(/-----BEGIN CERTIFICATE-----/g) ?? []).length;\n}\nif (chainDepth(\"example.com\") > 5) throw new Error(\"served chain suspiciously deep — trim fullchain.pem\");","typeGuard":"function isChainTooLong(e: unknown): e is Error & { code: \"CERT_CHAIN_TOO_LONG\" } {\n  return e instanceof Error && (e as any).code === \"CERT_CHAIN_TOO_LONG\";\n}","tryCatchPattern":"try { await fetch(url); } catch (e) { if (isChainTooLong(e)) { alertOps(\"trim fullchain.pem on \" + new URL(url).host); return cachedCopy(); } throw e; }","preventionTips":["Keep fullchain.pem to the minimal valid path; delete stale cross-signed entries","Automate chain assembly from the CA's current bundle on renewal","Verify chains in CI with openssl verify -show_chain"],"tags":["tls","certificate","chain","fetch","pki"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}