{"record":{"id":"1d1b280edbb7f33a","repo":"can1357/oh-my-pi","slug":"node-extra-ca-certs-path-does-not-exist-raw","errorCode":null,"errorMessage":"NODE_EXTRA_CA_CERTS path does not exist: ${raw}","messagePattern":"NODE_EXTRA_CA_CERTS path does not exist: (.+?)","errorType":"exception","errorClass":"ExtraCaError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/tls-fetch.ts","lineNumber":102,"sourceCode":"\tif (raw.includes(\"-----BEGIN\")) {\n\t\tkey = raw;\n\t} else {\n\t\ttry {\n\t\t\tkey = `${raw}@${fs.statSync(raw).mtimeMs}`;\n\t\t} catch {\n\t\t\tkey = raw;\n\t\t}\n\t}\n\tif (key === cacheKey) return cacheValue;\n\n\tif (raw.includes(\"-----BEGIN\")) {\n\t\tcacheValue = raw.replace(/\\\\n/g, \"\\n\");\n\t} else {\n\t\ttry {\n\t\t\tcacheValue = fs.readFileSync(raw, \"utf8\");\n\t\t} catch (error) {\n\t\t\tif (isEnoent(error)) {\n\t\t\t\tthrow new ExtraCaError(`NODE_EXTRA_CA_CERTS path does not exist: ${raw}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\tcacheKey = key;\n\treturn cacheValue;\n}\n\n/** Test seam: drop the cached PEM so a follow-up call re-reads the env. */\nexport function __resetExtraCaCache(): void {\n\tcacheKey = undefined;\n\tcacheValue = undefined;\n}\n\n/**\n * Merge `extraCa` into `init.tls.ca`. When the caller has not supplied a CA\n * list, the system root store is included alongside the extra bundle —\n * Bun's `tls.ca` replaces the default trust store, so omitting roots would","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/tls-fetch.ts#L84-L120","documentation":"resolveExtraCa() reads NODE_EXTRA_CA_CERTS: if the value contains escaped `\\n` it treats it as an inline PEM; otherwise it reads it as a file path. When the path cannot be read because it does not exist (ENOENT), it throws ExtraCaError(\"NODE_EXTRA_CA_CERTS path does not exist: <raw>\"). The result is cached, so a fixed value takes effect on subsequent calls.","triggerScenarios":"Setting NODE_EXTRA_CA_CERTS to a file path that does not exist (or with a typo) when making TLS requests via this fetch wrapper; pointing at a path valid on one machine but not on another (containers, CI).","commonSituations":"Corporate-proxy CA bundle path misconfigured in .env or CI secrets; copy-pasting a macOS path onto Linux; the CA file deleted by a cleanup step; forgetting to mount the cert file into a container.","solutions":["Check the env var value with `echo \"$NODE_EXTRA_CA_CERTS\"` and verify the file exists: `ls -l \"$NODE_EXTRA_CA_CERTS\"`.","Correct the path (or create the file with the CA PEM contents).","If you intended an inline certificate, embed it with literal `\\n` escapes instead of a path.","Unset NODE_EXTRA_CA_CERTS if no custom CA is actually needed; the error is cached, so restart/re-call after fixing only if the cache key changed to the new value."],"exampleFix":"// before\nNODE_EXTRA_CA_CERTS=/etc/ssl/corp-ca.pem   // file absent in container\n// after\nNODE_EXTRA_CA_CERTS=/usr/local/share/certs/corp-ca.pem   // mounted & exists","handlingStrategy":"validation","validationCode":"import * as fs from 'node:fs';\nconst raw = process.env.NODE_EXTRA_CA_CERTS;\nif (raw && !raw.includes('\\\\n')) {\n  if (!fs.existsSync(raw)) {\n    throw new Error(`NODE_EXTRA_CA_CERTS points to a missing file: ${raw}`);\n  }\n}","typeGuard":"function isInlinePem(value) {\n  return typeof value === 'string' && value.includes('\\\\n');\n}\nfunction caConfigIsValid(value) {\n  if (!value) return true;\n  if (isInlinePem(value)) return true;\n  return fs.existsSync(value);\n}","tryCatchPattern":"try {\n  await tlsFetch(url, { ...init });\n} catch (err) {\n  if (err?.name === 'ExtraCaError' && /path does not exist/.test(err.message)) {\n    throw new Error(`Fix NODE_EXTRA_CA_CERTS: ${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Verify the CA file exists at container/CI startup and fail fast with a clear message.","Mount the cert into containers explicitly and reference the mounted path.","Prefer inline `\\n`-escaped PEM when the file may not exist on all hosts.","Never assume a developer-machine path exists in production images."],"tags":["tls","configuration","env-var","certificate"],"backgroundTag":"node-extra-ca-certs-missing","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}