Follow-up to #4482 (our PR). Adopting runtime.frameworkRoutePrefix in a production app on 0.185.0 (Nitro node-server preset, React Router SSR with an app catch-all server/routes/[...page].get.ts, app middleware in server/middleware/ calling runAuthGuard), prefix /_api via AGENT_NATIVE_CONFIG_RUNTIME_FRAMEWORK_ROUTE_PREFIX.
1. Better Auth routes are rejected by the auth guard under the prefix. Built server (prefix present at build and at runtime):
| Request |
No prefix |
Prefix /_api |
POST …/auth/ba/sign-in/email (bad email) |
400 from Better Auth |
401 {"error":"Unauthorized"} |
POST …/auth/ba/sign-up/email |
200, session created |
401 {"error":"Unauthorized"} |
GET …/auth/session |
200 |
200 |
GET …/actions/<name> (no session) |
401 |
401 |
GET /_agent-native/… |
served |
404 (retired, as designed) |
So nobody can sign in with email/password once the prefix is set. The dev server (agent-native dev) shows the same shape plus POST /_api/auth/local-dev → 401. The guard builds its path from event.node?.req?.url ?? event.path; only event.url/event.path are rewritten by the boundary, so wherever the guard (or the Better Auth handler's own base-path check) sees the untranslated /_api/auth/ba/... it isn't matched as a public auth path. The same raw-URL read appears in google-oauth, security-headers, open-route, embed-session, identity-sso, mcp/connect-route and integrations/plugin.
2. The prefix only takes effect if it is present at build time. Set only at runtime on a server built without it, every /_api/* framework request fell through to the app's SSR catch-all (200 text/html) and /_agent-native/* kept serving. The env alias reads like a deploy-time switch; either honour it at runtime or document that it must be in the build environment (and fail loudly on a mismatch).
3. Docs note: app middleware that matches on new URL(event.req.url).pathname silently stops matching under a prefix (we had a staff-only guard on /_agent-native/observability); event.url.pathname is the translated path. Worth saying in the prefix docs, or exposing canonicalFrameworkPathname from a public subpath.
Happy to work on a fix; tracked in #5743.
Follow-up to #4482 (our PR). Adopting
runtime.frameworkRoutePrefixin a production app on 0.185.0 (Nitronode-serverpreset, React Router SSR with an app catch-allserver/routes/[...page].get.ts, app middleware inserver/middleware/callingrunAuthGuard), prefix/_apiviaAGENT_NATIVE_CONFIG_RUNTIME_FRAMEWORK_ROUTE_PREFIX.1. Better Auth routes are rejected by the auth guard under the prefix. Built server (prefix present at build and at runtime):
/_apiPOST …/auth/ba/sign-in/email(bad email){"error":"Unauthorized"}POST …/auth/ba/sign-up/email{"error":"Unauthorized"}GET …/auth/sessionGET …/actions/<name>(no session)GET /_agent-native/…So nobody can sign in with email/password once the prefix is set. The dev server (
agent-native dev) shows the same shape plusPOST /_api/auth/local-dev→ 401. The guard builds its path fromevent.node?.req?.url ?? event.path; onlyevent.url/event.pathare rewritten by the boundary, so wherever the guard (or the Better Auth handler's own base-path check) sees the untranslated/_api/auth/ba/...it isn't matched as a public auth path. The same raw-URL read appears ingoogle-oauth,security-headers,open-route,embed-session,identity-sso,mcp/connect-routeandintegrations/plugin.2. The prefix only takes effect if it is present at build time. Set only at runtime on a server built without it, every
/_api/*framework request fell through to the app's SSR catch-all (200 text/html) and/_agent-native/*kept serving. The env alias reads like a deploy-time switch; either honour it at runtime or document that it must be in the build environment (and fail loudly on a mismatch).3. Docs note: app middleware that matches on
new URL(event.req.url).pathnamesilently stops matching under a prefix (we had a staff-only guard on/_agent-native/observability);event.url.pathnameis the translated path. Worth saying in the prefix docs, or exposingcanonicalFrameworkPathnamefrom a public subpath.Happy to work on a fix; tracked in #5743.