can1357/oh-my-pi · error · ExtraCaError
NODE_EXTRA_CA_CERTS path does not exist: ${raw}
Error message
NODE_EXTRA_CA_CERTS path does not exist: ${raw} What it means
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.
Source
Thrown at packages/utils/src/tls-fetch.ts:102
if (raw.includes("-----BEGIN")) {
key = raw;
} else {
try {
key = `${raw}@${fs.statSync(raw).mtimeMs}`;
} catch {
key = raw;
}
}
if (key === cacheKey) return cacheValue;
if (raw.includes("-----BEGIN")) {
cacheValue = raw.replace(/\\n/g, "\n");
} else {
try {
cacheValue = fs.readFileSync(raw, "utf8");
} catch (error) {
if (isEnoent(error)) {
throw new ExtraCaError(`NODE_EXTRA_CA_CERTS path does not exist: ${raw}`);
}
throw error;
}
}
cacheKey = key;
return cacheValue;
}
/** Test seam: drop the cached PEM so a follow-up call re-reads the env. */
export function __resetExtraCaCache(): void {
cacheKey = undefined;
cacheValue = undefined;
}
/**
* Merge `extraCa` into `init.tls.ca`. When the caller has not supplied a CA
* list, the system root store is included alongside the extra bundle —
* Bun's `tls.ca` replaces the default trust store, so omitting roots wouldView on GitHub (pinned to 9690622007)
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.
Example fix
// before NODE_EXTRA_CA_CERTS=/etc/ssl/corp-ca.pem // file absent in container // after NODE_EXTRA_CA_CERTS=/usr/local/share/certs/corp-ca.pem // mounted & exists
Defensive patterns
Strategy: validation
Validate before calling
import * as fs from 'node:fs';
const raw = process.env.NODE_EXTRA_CA_CERTS;
if (raw && !raw.includes('\\n')) {
if (!fs.existsSync(raw)) {
throw new Error(`NODE_EXTRA_CA_CERTS points to a missing file: ${raw}`);
}
} Type guard
function isInlinePem(value) {
return typeof value === 'string' && value.includes('\\n');
}
function caConfigIsValid(value) {
if (!value) return true;
if (isInlinePem(value)) return true;
return fs.existsSync(value);
} Try / catch
try {
await tlsFetch(url, { ...init });
} catch (err) {
if (err?.name === 'ExtraCaError' && /path does not exist/.test(err.message)) {
throw new Error(`Fix NODE_EXTRA_CA_CERTS: ${err.message}`);
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL
- ${name} path does not exist: ${trimmed}
- Invalid GITLAB_REDIRECT_URI: ${raw}
- GITLAB_REDIRECT_URI must use http:// or https://, got: ${raw
- GITLAB_REDIRECT_URI loopback callbacks must use http://, got
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1d1b280edbb7f33a.
Report an issue: GitHub.