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 would

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the env var value with `echo "$NODE_EXTRA_CA_CERTS"` and verify the file exists: `ls -l "$NODE_EXTRA_CA_CERTS"`.
  2. Correct the path (or create the file with the CA PEM contents).
  3. If you intended an inline certificate, embed it with literal `\n` escapes instead of a path.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1d1b280edbb7f33a. Report an issue: GitHub.