{"record":{"id":"b93057b9578a37d0","repo":"oven-sh/bun","slug":"application-verification","errorCode":"APPLICATION_VERIFICATION","errorMessage":"APPLICATION_VERIFICATION","messagePattern":"APPLICATION_VERIFICATION","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":221,"sourceCode":"    #[error(\"INVALID_EXTENSION\")]\n    INVALID_EXTENSION,\n    #[error(\"INVALID_POLICY_EXTENSION\")]\n    INVALID_POLICY_EXTENSION,\n    #[error(\"NO_EXPLICIT_POLICY\")]\n    NO_EXPLICIT_POLICY,\n    #[error(\"DIFFERENT_CRL_SCOPE\")]\n    DIFFERENT_CRL_SCOPE,\n    #[error(\"UNSUPPORTED_EXTENSION_FEATURE\")]\n    UNSUPPORTED_EXTENSION_FEATURE,\n    #[error(\"UNNESTED_RESOURCE\")]\n    UNNESTED_RESOURCE,\n    #[error(\"PERMITTED_VIOLATION\")]\n    PERMITTED_VIOLATION,\n    #[error(\"EXCLUDED_VIOLATION\")]\n    EXCLUDED_VIOLATION,\n    #[error(\"SUBTREE_MINMAX\")]\n    SUBTREE_MINMAX,\n    #[error(\"APPLICATION_VERIFICATION\")]\n    APPLICATION_VERIFICATION,\n    #[error(\"UNSUPPORTED_CONSTRAINT_TYPE\")]\n    UNSUPPORTED_CONSTRAINT_TYPE,\n    #[error(\"UNSUPPORTED_CONSTRAINT_SYNTAX\")]\n    UNSUPPORTED_CONSTRAINT_SYNTAX,\n    #[error(\"UNSUPPORTED_NAME_SYNTAX\")]\n    UNSUPPORTED_NAME_SYNTAX,\n    #[error(\"CRL_PATH_VALIDATION_ERROR\")]\n    CRL_PATH_VALIDATION_ERROR,\n    #[error(\"SUITE_B_INVALID_VERSION\")]\n    SUITE_B_INVALID_VERSION,\n    #[error(\"SUITE_B_INVALID_ALGORITHM\")]\n    SUITE_B_INVALID_ALGORITHM,\n    #[error(\"SUITE_B_INVALID_CURVE\")]\n    SUITE_B_INVALID_CURVE,\n    #[error(\"SUITE_B_INVALID_SIGNATURE_ALGORITHM\")]\n    SUITE_B_INVALID_SIGNATURE_ALGORITHM,\n    #[error(\"SUITE_B_LOS_NOT_ALLOWED\")]","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L203-L239","documentation":"CertError::APPLICATION_VERIFICATION maps BoringSSL X509_V_ERR_APPLICATION_VERIFICATION (verify code 50). It is the catch-all set when verification fails at the application layer: the app-supplied verify callback rejected the chain, or the verification context was invoked with parameters that let no more specific code apply. Message: \"application verification failure\". Treat it as 'the verifier said no for a reason it did not classify'.","triggerScenarios":"An application verify callback returns 0 without a preceding specific X509 error; verification requested with mismatched parameters (e.g. purpose/hostname handling done app-side and failing); intermediaries that terminate and re-verify TLS with their own callback rejecting the upstream chain.","commonSituations":"Corporate proxies or AV middleware re-verifying upstream and passing the verdict down as a generic failure; hostname checks performed by a callback rather than built-in SAN matching; runtime/library upgrades changing callback semantics; containers missing their CA bundle causing callbacks to fail open-or-closed differently.","solutions":["Get the real verdict out-of-band: openssl s_client -connect host:443 -verify_return_error -servername host","Check hostname vs SAN first - app-level hostname rejection commonly lands here","Review any custom verify-callback/proxy logic between your code and the server; this code often means that layer rejected, not the raw chain","Reproduce with a fresh trust store (SSL_CERT_FILE / NODE_EXTRA_CA_CERTS) to rule out store problems"],"exampleFix":"// before: app callback rejects without detail\nfunction verifyCb(ok) { return ok && allowedHosts.has(url.host); }\n\n// after: classify failures so the error you see is actionable\nfunction verifyCb(ok, ctx) {\n  if (!ok) console.error('verify failed:', ctx.error, ctx.errorString);\n  return ok;\n}","handlingStrategy":"try-catch","validationCode":"// Get the real verify verdict before the app-level call, so a generic failure becomes specific\nimport { execFileSync } from \"node:child_process\";\nexport function strictVerify(host, port = 443, ca = \"/etc/ssl/cert.pem\") {\n  execFileSync(\"openssl\", [\"s_client\", \"-connect\", `${host}:${port}`, \"-servername\", host, \"-verify_return_error\", \"-CAfile\", ca], { input: \"\", stdio: \"pipe\" });\n  return true; // throws with the underlying X509 code\n}","typeGuard":"export function isApplicationVerification(e): e is Error & { code: \"APPLICATION_VERIFICATION\" } {\n  return e instanceof Error && (e as any).code === \"APPLICATION_VERIFICATION\";\n}","tryCatchPattern":"try {\n  await fetch(url);\n} catch (e) {\n  if (e?.code === \"APPLICATION_VERIFICATION\") {\n    // catch-all: run openssl s_client -verify_return_error to get the specific cause, check proxy callbacks\n    const detail = await diagnoseWithOpenssl(url);\n    log({ url, detail });\n  } else throw e;\n}","preventionTips":["Treat APPLICATION_VERIFICATION as 'unknown cause' - always follow up with -verify_return_error before changing anything","Make custom verify callbacks emit the underlying ctx.error so this code stops swallowing detail","Watch for TLS-terminating middleboxes: their verdict arrives as this generic code","Keep the trust store pinned and versioned in images to rule out store drift"],"tags":["tls","x509","verification","fetch","security","diagnostics"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}