{"record":{"id":"d0153c649d9b745e","repo":"oven-sh/bun","slug":"invalid-ca","errorCode":"INVALID_CA","errorMessage":"INVALID_CA","messagePattern":"INVALID_CA","errorType":"error_code","errorClass":"CertError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":169,"sourceCode":"    #[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\")]\n    AKID_ISSUER_SERIAL_MISMATCH,\n    #[error(\"KEYUSAGE_NO_CERTSIGN\")]\n    KEYUSAGE_NO_CERTSIGN,\n    #[error(\"UNABLE_TO_GET_CRL_ISSUER\")]","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L151-L187","documentation":"CertError::INVALID_CA maps BoringSSL X509 verify code 24 (X509_V_ERR_INVALID_CA) via get_cert_error_from_no() in src/http/lib.rs:1543. A certificate used as a CA in the path is not actually a CA: its Basic Constraints lack CA:TRUE, or its key type/usage disallows acting as one. JS error.code is INVALID_CA with message 'invalid CA certificate' (FetchTasklet.rs:1440).","triggerScenarios":"A self-signed leaf minted with openssl req -x509 WITHOUT basicConstraints=CA:TRUE is passed via tls: { ca } or installed as a root; an intermediate in the served chain lacks CA:TRUE; a server cert being used to sign another cert.","commonSituations":"Dev/test self-signed certs generated with defaults used as trust anchors (very common in docker-compose local stacks), mkcert-less local CA attempts, private PKI where the intermediate template omitted Basic Constraints.","solutions":["Regenerate the CA with explicit CA:TRUE (see exampleFix) and reissue the leaf from it","Check the intermediate: openssl x509 -in int.pem -text -noout | grep -A2 'Basic Constraints' must show CA:TRUE","Serve/anchor the correct intermediate that actually has CA:TRUE","Pass the real CA (the one that signed the leaf) in tls: { ca }, not the leaf itself"],"exampleFix":"# before: leaf-style self-signed cert used as CA\nopenssl req -x509 -newkey rsa:2048 -keyout k.pem -out c.pem -days 30\n# after: proper CA with Basic Constraints\nopenssl req -x509 -newkey rsa:2048 -keyout ca-key.pem -out ca.pem -days 3650 \\\n  -addext 'basicConstraints=critical,CA:TRUE' \\\n  -addext 'keyUsage=critical,keyCertSign,cRLSign'","handlingStrategy":"validation","validationCode":"import { X509Certificate } from \"node:crypto\";\nconst ca = new X509Certificate(await Bun.file(\"ca.pem\").text());\nif (!ca.ca) throw new Error(\"ca.pem lacks BasicConstraints CA:TRUE — regenerate it before using as tls.ca\");\nawait fetch(url, { tls: { ca: ca.raw.toString() } });","typeGuard":"function isInvalidCa(e: unknown): e is Error & { code: \"INVALID_CA\" } {\n  return e instanceof Error && (e as any).code === \"INVALID_CA\";\n}","tryCatchPattern":"try { await fetch(url, { tls: { ca } }); } catch (e) { if (isInvalidCa(e)) { failFast(\"trust anchor is not a real CA — fix ca.pem generation\"); } throw e; }","preventionTips":["Generate test CAs with basicConstraints=critical,CA:TRUE and keyUsage=keyCertSign,cRLSign","Programmatically assert X509Certificate#ca === true before installing anchors","Keep a canonical CA-creation script instead of ad-hoc openssl req -x509 calls"],"tags":["tls","certificate","ca","pki","fetch"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}