fix: add has trap to lazy auth proxy so auth routes resolve handler#139
Merged
Conversation
The lazy `auth` Proxy only trapped `get`, leaving `has` to forward to its empty target. better-auth's `toNextJsHandler` checks `"handler" in auth` per request; that returned false, so it fell through to calling `auth(request)`, which isn't callable. Result: every /api/auth/* POST threw "TypeError: ... is not a function" in production (e.g. sign-in/social). Add a `has` trap forwarding to the real instance. Stays build-time safe: the check only runs inside toNextJsHandler's per-request closure, never at module load, so env-validation decoupling is preserved.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
formbase-web | 6b8331f | Jun 01 2026, 10:02 AM |
The get-traps assigned `Reflect.get(...)`'s `any` return, tripping
@typescript-eslint/no-unsafe-{assignment,return,call,member-access} (12
errors, pre-existing red on main since the proxies landed). Annotate the
forwarded value as `unknown` and cast on the function branch so binding is
type-checked. Runtime behavior is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In production (Cloudflare Workers), every
POST /api/auth/*returned500withTypeError: e8 is not a function, breaking sign-in (observed on/api/auth/sign-in/social).Root cause
packages/auth/index.tsexposesauthas a lazynew Proxy({}, { get })to defercreateAuth()past build-time env validation. It trapped onlyget— nothas.better-auth's
toNextJsHandlerruns this per request:With no
hastrap,"handler" in authforwards to the empty proxy target{}→false, so better-auth falls through toauth(request). The proxy isn't callable →TypeError: auth is not a function(minified toe8).This breaks all
/api/auth/*HTTP routes (social and email). Server-sideauth.api.getSession(...)was unaffected because it goes through thegettrap — which is why page session checks kept working and only the sign-in POSTs 500'd.Fix
Add a
hastrap that forwards to the real instance:Build-time safe:
toNextJsHandleronly evaluates"handler" in authinside its per-request closure, never at module load, so the env-validation decoupling is preserved.Verification
Reproduced against the actual published
better-auth@1.4.10+toNextJsHandler, posting to/api/auth/sign-in/social:TypeError: auth is not a function— matches prode8.hastrap):200with{"url":"https://github.com/login/oauth/authorize?..."}.Note
Deploying this requires a Worker rebuild + redeploy to ship the new bundle. No env/secret/DNS changes needed.