You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
v4: auth0.middleware() crashes with "Cannot read properties of undefined (reading 'provider')" when invoked from proxy.ts under Next.js 16 (works from a Route Handler) #2781
auth0.middleware() throws TypeError: Cannot read properties of undefined (reading 'provider') on every request when invoked from proxy.ts under Next.js 16. Reproduced identically in both next dev and next start (production build) — not a dev-only artifact.
The most diagnostic detail: the identical auth0.middleware() call succeeds when dispatched from a Route Handler and fails when dispatched from proxy.ts. Same Auth0Client instance, same request, two different call sites:
GET /api/auth/login (dispatched from app/api/auth/[auth0]/route.ts, calling auth0.middleware(req) directly inside a GET handler) → works correctly. Clean 307 to the real Auth0 /authorize endpoint with correct client_id, PKCE code_challenge, state, nonce, and a properly-set transaction cookie.
GET /login (an ordinary app page, covered by proxy.ts's matcher) → crashes with the trace below, on every request, no exceptions.
I initially suspected this might be an Edge-vs-Node runtime difference, since the working call site is a Node.js Route Handler. I tested this directly by adding export const runtime = "nodejs" to proxy.ts — Next.js rejected it outright at build time: Error: Route segment config is not allowed in Proxy file... Proxy always runs on Node.js runtime. So there is no Edge/Node distinction to invoke here; proxy.ts is already Node-only under Next 16, and the crash happens anyway. I was not able to narrow the root cause further than that structural contrast.
Also ruled out: fake/placeholder Auth0 credentials (re-tested against a real, valid Auth0 tenant and real client credentials — identical crash); an SDK version predating Next 16 support (this is reproduced on 4.25.0, whose own peerDependencies list next: "... || ^16.0.10"); the SDK's env-var-lazy domain resolver (passed domain explicitly instead of relying on the AUTH0_DOMAIN fallback — identical crash).
Workaround in use: removed proxy.ts entirely. Route mounting still works via the Route Handler (route.ts), and route protection is handled by each protected layout calling auth0.getSession() directly rather than relying on the proxy. The only capability lost is automatic rolling-session refresh.
Set real (or placeholder — both reproduce it) AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, AUTH0_SECRET, AUTH0_BASE_URL env vars.
next build && next start, then request any page not excluded by the matcher (e.g. /).
Expect: normal page response. Actual: 500, with the trace below in the server log.
Additional context
Full trace (paths are the local build output; the specific file/hash naturally varies by build):
TypeError: Cannot read properties of undefined (reading 'provider')
at middleware (.next\server\chunks\[root-of-the-server]__<hash>._.js:31:138428)
at handler (.next\server\chunks\[root-of-the-server]__<hash>._.js:34:1616)
at <unknown> (.next\server\chunks\[root-of-the-server]__<hash>._.js:15:37004)
at <unknown> (.next\server\chunks\[root-of-the-server]__<hash>._.js:15:36970)
at async t2 (.next\server\chunks\[root-of-the-server]__<hash>._.js:15:33484)
Looking at dist/server/client.js (~line 195–243), the constructor's own comments describe an initialization-order dependency: this.provider is assigned via new AuthClientProvider(...), and a factory closure captures this by reference intending to read this.provider only after that assignment completes, with an explicit static-mode workaround for the case where "the factory ... is called during AuthClientProvider construction, before this.provider is fully assigned." That reads like the class of race the crash matches, but I wasn't able to confirm it's the same code path triggering under the proxy specifically.
nextjs-auth0 version
4.25.0 (also reproduced on 4.22.0 before upgrading)
Checklist
Description
auth0.middleware()throwsTypeError: Cannot read properties of undefined (reading 'provider')on every request when invoked fromproxy.tsunder Next.js 16. Reproduced identically in bothnext devandnext start(production build) — not a dev-only artifact.The most diagnostic detail: the identical
auth0.middleware()call succeeds when dispatched from a Route Handler and fails when dispatched fromproxy.ts. SameAuth0Clientinstance, same request, two different call sites:GET /api/auth/login(dispatched fromapp/api/auth/[auth0]/route.ts, callingauth0.middleware(req)directly inside aGEThandler) → works correctly. Clean307to the real Auth0/authorizeendpoint with correctclient_id, PKCEcode_challenge,state,nonce, and a properly-set transaction cookie.GET /login(an ordinary app page, covered byproxy.ts's matcher) → crashes with the trace below, on every request, no exceptions.I initially suspected this might be an Edge-vs-Node runtime difference, since the working call site is a Node.js Route Handler. I tested this directly by adding
export const runtime = "nodejs"toproxy.ts— Next.js rejected it outright at build time:Error: Route segment config is not allowed in Proxy file... Proxy always runs on Node.js runtime.So there is no Edge/Node distinction to invoke here;proxy.tsis already Node-only under Next 16, and the crash happens anyway. I was not able to narrow the root cause further than that structural contrast.Also ruled out: fake/placeholder Auth0 credentials (re-tested against a real, valid Auth0 tenant and real client credentials — identical crash); an SDK version predating Next 16 support (this is reproduced on 4.25.0, whose own
peerDependencieslistnext: "... || ^16.0.10"); the SDK's env-var-lazy domain resolver (passeddomainexplicitly instead of relying on theAUTH0_DOMAINfallback — identical crash).Workaround in use: removed
proxy.tsentirely. Route mounting still works via the Route Handler (route.ts), and route protection is handled by each protected layout callingauth0.getSession()directly rather than relying on the proxy. The only capability lost is automatic rolling-session refresh.Reproduction
npx create-next-app@latest --typescript@auth0/nextjs-auth0(4.25.0) and configure a minimalAuth0Clientin e.g.auth.ts:proxy.tsat the project root per the v4 migration guide's Next 16 section:AUTH0_DOMAIN,AUTH0_CLIENT_ID,AUTH0_CLIENT_SECRET,AUTH0_SECRET,AUTH0_BASE_URLenv vars.next build && next start, then request any page not excluded by the matcher (e.g./).500, with the trace below in the server log.Additional context
Full trace (paths are the local build output; the specific file/hash naturally varies by build):
Looking at
dist/server/client.js(~line 195–243), the constructor's own comments describe an initialization-order dependency:this.provideris assigned vianew AuthClientProvider(...), and a factory closure capturesthisby reference intending to readthis.provideronly after that assignment completes, with an explicit static-mode workaround for the case where "the factory ... is called during AuthClientProvider construction, before this.provider is fully assigned." That reads like the class of race the crash matches, but I wasn't able to confirm it's the same code path triggering under the proxy specifically.nextjs-auth0 version
4.25.0 (also reproduced on 4.22.0 before upgrading)
Next.js version
16.2.12 (Turbopack)
Node.js version
24.14.1