{"record":{"id":"e6c1a0ad7df73247","repo":"oven-sh/bun","slug":"invalidca","errorCode":null,"errorMessage":"InvalidCA","messagePattern":"InvalidCA","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/http/InitError.rs","lineNumber":9,"sourceCode":"#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, strum::IntoStaticStr)]\npub enum InitError {\n    #[error(\"FailedToOpenSocket\")]\n    FailedToOpenSocket,\n    #[error(\"LoadCAFile\")]\n    LoadCAFile,\n    #[error(\"InvalidCAFile\")]\n    InvalidCAFile,\n    #[error(\"InvalidCA\")]\n    InvalidCA,\n    #[error(\"InvalidCRL\")]\n    InvalidCRL,\n}\n","sourceCodeStart":1,"sourceCodeEnd":14,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/InitError.rs#L1-L14","documentation":"An inline CA certificate (passed as cert data rather than a file path — uws invalid_ca mapped at src/http/HTTPContext.rs:520; message 'the provided CA is invalid' at src/http/HTTPThread.rs:369-371) failed to parse. This covers CA material supplied through APIs that feed BunSocketContextOptions.ca (inline PEM strings in fetch/Bun.connect-style TLS options or install config `ca` entries).","triggerScenarios":"Passing an inline PEM string that is truncated, has escaped newlines mangled by JSON/env interpolation, uses CRLF line endings from a Windows secret, or contains a non-CA end-entity certificate as the trust anchor.","commonSituations":"Secrets managers storing the PEM as a single-line string with literal '\\n' that never get converted to real newlines; env-var CA data base64'd once too many/few times; corporate MITM proxies documented to hand out leaf certs instead of the root.","solutions":["Round-trip the inline CA through a parser before handing it to Bun: `Bun.file`-free check with `openssl x509 -noout -subject` via stdin, or in JS verify it starts with '-----BEGIN CERTIFICATE-----'.","Fix newline handling: replace literal '\\\\n' sequences with '\\n' and ensure LF endings.","Prefer `cafile` with a verified PEM on disk over inline strings when possible — it gets clearer diagnostics (LoadCAFile vs InvalidCAFile).","Make sure you pass the root/intermediate CA, not the server's leaf certificate."],"exampleFix":"// before: secret stored single-line\nconst ca = process.env.CA_PEM; // \"-----BEGIN CERTIFICATE-----\\\\nMIIF...\\\\n\" with literal backslash-n\nawait fetch('https://internal', { tls: { ca } });\n// after\nconst ca = process.env.CA_PEM!.replace(/\\\\n/g, '\\n');\nawait fetch('https://internal', { tls: { ca } });","handlingStrategy":"validation","validationCode":"function isPemCert(s) {\n  return typeof s === 'string' &&\n    s.startsWith('-----BEGIN CERTIFICATE-----') &&\n    s.includes('-----END CERTIFICATE-----') &&\n    !s.includes('PRIVATE KEY');\n}\nconst ca = process.env.CA_PEM!.replace(/\\\\n/g, '\\n');\nif (!isPemCert(ca)) throw new Error('inline CA is not a PEM certificate');\nawait fetch('https://internal', { tls: { ca } });","typeGuard":"function isPemCert(value) {\n  return typeof value === 'string' &&\n    /^-----BEGIN CERTIFICATE-----[\\s\\S]+-----END CERTIFICATE-----/.test(value);\n}","tryCatchPattern":null,"preventionTips":["Normalize literal '\\\\n' to real newlines when CAs come from env/secrets","Pass root/intermediate CAs, never leaf certificates","Prefer cafile over inline strings for clearer diagnostics"],"tags":["tls","ca","pem","secrets","crash"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}