{"record":{"id":"a5730d5142eaba94","repo":"can1357/oh-my-pi","slug":"name-path-does-not-exist-trimmed","errorCode":null,"errorMessage":"${name} path does not exist: ${trimmed}","messagePattern":"(.+?) path does not exist: (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/anthropic.ts","lineNumber":1300,"sourceCode":"function looksLikeFilePath(value: string): boolean {\n\treturn value.includes(\"/\") || value.includes(\"\\\\\") || /\\.(pem|crt|cer|key)$/i.test(value);\n}\n\nfunction resolvePemValue(value: string | undefined, name: string): string | undefined {\n\tconst trimmed = value?.trim();\n\tif (!trimmed) return undefined;\n\n\tconst inline = trimmed.replace(/\\\\n/g, \"\\n\");\n\tif (inline.includes(\"-----BEGIN\")) {\n\t\treturn inline;\n\t}\n\n\tif (looksLikeFilePath(trimmed)) {\n\t\ttry {\n\t\t\treturn fs.readFileSync(trimmed, \"utf8\");\n\t\t} catch (error) {\n\t\t\tif (isEnoent(error)) {\n\t\t\t\tthrow new AIError.ValidationError(`${name} path does not exist: ${trimmed}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\treturn inline;\n}\n\nfunction resolveFoundryTlsOptions(model: Model<\"anthropic-messages\">): FoundryTlsOptions | undefined {\n\tif (model.provider !== \"anthropic\") return undefined;\n\tif (!isFoundryEnabled()) return undefined;\n\n\tconst cacheKey = foundryTlsOptionsCacheKey();\n\tif (foundryTlsOptionsCache.has(cacheKey)) return foundryTlsOptionsCache.get(cacheKey);\n\n\tconst ca = resolvePemValue($env.NODE_EXTRA_CA_CERTS, \"NODE_EXTRA_CA_CERTS\");\n\tconst cert = resolvePemValue($env.CLAUDE_CODE_CLIENT_CERT, \"CLAUDE_CODE_CLIENT_CERT\");\n\tconst key = resolvePemValue($env.CLAUDE_CODE_CLIENT_KEY, \"CLAUDE_CODE_CLIENT_KEY\");","sourceCodeStart":1282,"sourceCodeEnd":1318,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/anthropic.ts#L1282-L1318","documentation":"resolvePemValue accepts a TLS/SSH key material either inline (a PEM string containing '-----BEGIN') or as a file path. When the value looks like a path (contains / or \\ or ends in .pem/.crt/.cer/.key) but reading it fails with ENOENT, the library throws a ValidationError naming the parameter and the path. This is a configuration error: the caller pointed a cert/key option at a file that does not exist.","triggerScenarios":"Passing a path to a PEM option (client certificate/key, CA bundle for Foundry TLS, mTLS settings) where the file is missing — wrong relative path, file deleted, secret not mounted in the container, or an inline key whose newlines were mangled so it no longer contains '-----BEGIN' and is therefore treated as a path.","commonSituations":"Kubernetes/containers where the secret volume wasn't mounted at the expected path; env vars set with escaped \\n that collapsed incorrectly; running from a different working directory so relative paths break; copying config between machines where cert files live elsewhere.","solutions":["Verify the file exists at the exact path given (ls the path with the same user/working directory the app runs as)","Use absolute paths in configuration so the app's CWD cannot change resolution","If embedding the key inline, ensure it contains the full '-----BEGIN ... PRIVATE KEY-----' header and real newlines (or literal \\n escapes)","In containers, confirm the secret mount and volume mountPath match the configured path","Catch this ValidationError at startup and fail fast with a clear config-error message instead of at first request"],"exampleFix":"// before: relative path, breaks when CWD changes\ntls: { keyFile: \"certs/client-key.pem\" }\n// after: absolute path + existence check at boot\nconst keyPath = path.resolve(process.env.KEY_DIR ?? \"/etc/app/certs\", \"client-key.pem\");\nif (!fs.existsSync(keyPath)) throw new Error(`Missing TLS key: ${keyPath}`);\ntls: { keyFile: keyPath }","handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs\";\nfunction assertPemReadable(name: string, value: string | undefined): void {\n  const trimmed = value?.trim();\n  if (!trimmed) return;\n  if (trimmed.includes(\"-----BEGIN\")) return;\n  if (trimmed.includes(\"/\") || trimmed.includes(\"\\\\\") || /\\.(pem|crt|cer|key)$/i.test(trimmed)) {\n    if (!fs.existsSync(trimmed)) throw new Error(`${name} path does not exist: ${trimmed}`);\n  }\n}","typeGuard":"function isPemMaterial(value: string): boolean {\n  return value.includes(\"-----BEGIN\");\n}","tryCatchPattern":"try {\n  await createProvider(opts);\n} catch (err) {\n  if (err instanceof AIError.ValidationError && err.message.includes(\"path does not exist\")) {\n    // config error: cert/key file missing; fail fast with actionable guidance\n    throw new Error(`TLS config error — ${err.message}. Check secret mounts and use absolute paths.`);\n  }\n  throw err;\n}","preventionTips":["Use absolute paths for cert/key files and verify them at startup, not first request","Confirm container secret mounts match configured paths in staging before prod","When inlining PEM, keep the BEGIN header intact so it isn't misparsed as a path","Beware escaped-\\n env vars: unescape them consistently before passing key material"],"tags":["validation","tls","configuration","file-not-found"],"backgroundTag":"missing-file-path","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}