Summary
getAppCheck().verifyToken() throws ERR_REQUIRE_ESM in a CommonJS/serverless runtime. The transitive dep jwks-rsa@4.0.1 does const jose = require('jose') but declares jose@^6.1.3, and jose@6 is ESM-only, so the require() is a hard Node error.
Error
Error [ERR_REQUIRE_ESM]: require() of ES Module
node_modules/.pnpm/jose@6.2.3/node_modules/jose/dist/webapi/index.js
from node_modules/.pnpm/jwks-rsa@4.0.1/node_modules/jwks-rsa/src/utils.js
not supported.
Root cause (verified)
firebase-admin@14.0.0 App Check verification depends on jwks-rsa@4.0.1.
jwks-rsa@4.0.1 declares "jose": "^6.1.3" and loads it via CommonJS in src/utils.js:
const jose = require('jose');
jose@6.2.3 is ESM-only ("type": "module", no require export condition).
- Node refuses
require() of an ESM module, so any path reaching App Check JWKS verification crashes.
jwks-rsa@4.0.1 is internally inconsistent: a CommonJS require('jose') paired with a jose range whose only satisfying versions are ESM-only. firebase-admin ships this combination. It only uses jose.importJWK and jose.exportSPKI, which are API-identical across jose 4/5/6.
Why production only
Dev uses an ESM-capable loader, so the import resolves via interop. In a production CommonJS/serverless bundle (firebase-admin is externalized and loaded with require()), the require()-of-ESM hits the hard error.
Environment
- firebase-admin: 14.0.0
- jwks-rsa: 4.0.1 (transitive)
- jose resolved: 6.2.3 (ESM-only)
- Node.js 20+, CommonJS context, serverless (Vercel), Next.js 16, pnpm 11
Expected
App Check verification works in a CommonJS/serverless runtime without manual dependency overrides.
Suggested fix
Move jwks-rsa to a version that loads jose via dynamic import(), or constrain jose to a dual CJS/ESM build (^4/^5), or pin/patch jwks-rsa's jose in firebase-admin.
Workaround (consumer side)
# pnpm-workspace.yaml
overrides:
jwks-rsa>jose: "4.15.9"
Summary
getAppCheck().verifyToken()throwsERR_REQUIRE_ESMin a CommonJS/serverless runtime. The transitive depjwks-rsa@4.0.1doesconst jose = require('jose')but declaresjose@^6.1.3, and jose@6 is ESM-only, so therequire()is a hard Node error.Error
Root cause (verified)
firebase-admin@14.0.0App Check verification depends onjwks-rsa@4.0.1.jwks-rsa@4.0.1declares"jose": "^6.1.3"and loads it via CommonJS insrc/utils.js:jose@6.2.3is ESM-only ("type": "module", norequireexport condition).require()of an ESM module, so any path reaching App Check JWKS verification crashes.jwks-rsa@4.0.1is internally inconsistent: a CommonJSrequire('jose')paired with ajoserange whose only satisfying versions are ESM-only.firebase-adminships this combination. It only usesjose.importJWKandjose.exportSPKI, which are API-identical across jose 4/5/6.Why production only
Dev uses an ESM-capable loader, so the import resolves via interop. In a production CommonJS/serverless bundle (
firebase-adminis externalized and loaded withrequire()), therequire()-of-ESM hits the hard error.Environment
Expected
App Check verification works in a CommonJS/serverless runtime without manual dependency overrides.
Suggested fix
Move
jwks-rsato a version that loadsjosevia dynamicimport(), or constrainjoseto a dual CJS/ESM build (^4/^5), or pin/patchjwks-rsa'sjoseinfirebase-admin.Workaround (consumer side)