{"record":{"id":"fe3e974a6517c5a2","repo":"oven-sh/bun","slug":"akid-issuer-serial-mismatch","errorCode":"AKID_ISSUER_SERIAL_MISMATCH","errorMessage":"AKID_ISSUER_SERIAL_MISMATCH","messagePattern":"AKID_ISSUER_SERIAL_MISMATCH","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":183,"sourceCode":"    #[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\")]\n    UNABLE_TO_GET_CRL_ISSUER,\n    #[error(\"UNHANDLED_CRITICAL_EXTENSION\")]\n    UNHANDLED_CRITICAL_EXTENSION,\n    #[error(\"KEYUSAGE_NO_CRL_SIGN\")]\n    KEYUSAGE_NO_CRL_SIGN,\n    #[error(\"UNHANDLED_CRITICAL_CRL_EXTENSION\")]\n    UNHANDLED_CRITICAL_CRL_EXTENSION,\n    #[error(\"INVALID_NON_CA\")]\n    INVALID_NON_CA,\n    #[error(\"PROXY_PATH_LENGTH_EXCEEDED\")]\n    PROXY_PATH_LENGTH_EXCEEDED,\n    #[error(\"KEYUSAGE_NO_DIGITAL_SIGNATURE\")]\n    KEYUSAGE_NO_DIGITAL_SIGNATURE,\n    #[error(\"PROXY_CERTIFICATES_NOT_ALLOWED\")]","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L165-L201","documentation":"CertError::AKID_ISSUER_SERIAL_MISMATCH maps BoringSSL X509 verify code 31 (X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH) via get_cert_error_from_no() in src/http/lib.rs:1550. The certificate's Authority Key Identifier carries the optional issuer/serial form, and that issuer-and-serial pair does not locate the actual issuer certificate in the chain. JS error.code is AKID_ISSUER_SERIAL_MISMATCH with message 'authority and issuer serial number mismatch' (FetchTasklet.rs:1475).","triggerScenarios":"AKID written in the (rare) issuerName+serialNumber form pointing at a different certificate (different serial) than the one actually used to sign; chain assembled with a reissued/serial-changed intermediate while the leaf's AKID serial points at the previous one.","commonSituations":"Private CAs that emit the issuer/serial AKID variant, CA certificate reissue (new serial, same key and name) without reissuing leafs, hand-built chains from mixed issuance generations.","solutions":["Dump AKID of the leaf: openssl x509 -in leaf.pem -noout -text | grep -A2 'Authority Key Identifier' and check the serial it names","Reissue the leaf (or the whole chain) so AKID and issuer serials are consistent","If you control the CA tooling, prefer the keyIdentifier (SKI-hash) AKID form when creating certs","Verify the rebuilt chain: openssl verify -show_chain -untrusted intermediates.pem leaf.pem"],"exampleFix":"# before\nleaf(AKI serial 1A2B) + intermediate(serial 3C4D)\n# after\nleaf(AKI serial 1A2B) + intermediate(serial 1A2B)  # reissued/served matching serial\nopenssl x509 -in int.pem -noout -serial  # confirm it equals the AKID serial","handlingStrategy":"try-catch","validationCode":"import { X509Certificate } from \"node:crypto\";\nconst leaf = new X509Certificate(await Bun.file(\"leaf.pem\").text());\nconst text = await Bun.$`openssl x509 -in leaf.pem -noout -text`.text();\nconst akiSerial = text.match(/Authority Key Identifier:[\\s\\S]*?serial:([0-9A-F]+)/)?.[1];\nif (akiSerial) {\n  const intSerial = (await Bun.$`openssl x509 -in intermediate.pem -noout -serial`.text()).split(\"=\")[1];\n  if (akiSerial !== intSerial) throw new Error(\"AKID issuer/serial does not match served intermediate serial\");\n}","typeGuard":"function isAkidIssuerSerialMismatch(e: unknown): e is Error & { code: \"AKID_ISSUER_SERIAL_MISMATCH\" } {\n  return e instanceof Error && (e as any).code === \"AKID_ISSUER_SERIAL_MISMATCH\";\n}","tryCatchPattern":"try { await fetch(url); } catch (e) { if (isAkidIssuerSerialMismatch(e)) { rebuildChainFromCA(new URL(url).host); throw e; } throw e; }","preventionTips":["Prefer keyIdentifier-form AKI in your CA tooling","Reissue the full chain on serial-changing CA reissues","Lint AKID serials against issuer serials in CI"],"tags":["tls","certificate","pki","akid","chain"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}