better-auth adapter: update() with compound where fails (deviceAuthorization verify-claim) — no updateMany fallback
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- authentication
Research direction
Start in packages/auth-adapters/better-auth/src/adapter.ts: read convertWhereClause() (L47-90) and update() (L146-152), then compare with the updateMany() implementation directly below. Decide whether the converted where is a single top-level unique selector and route non-unique compounds through updateMany, optionally re-reading by the unique field. Reproduce with the deviceAuthorization verify step on DeviceCode; done when that update no longer raises 'At least one unique field must be set at where' and the adapter tests pass.
Written by the indexing model from the issue text.
Description
Summary
@zenstackhq/better-auth's update() forwards a compound (AND) where straight to ZenStack ORM update(), which requires a unique field at the top level of where. Any better-auth flow that updates by a multi-condition where therefore fails before SQL runs. This is now hit in normal usage by better-auth's deviceAuthorization plugin.
Environment
@zenstackhq/better-auth: 3.3.3 and 3.7.2 (latest) — same behaviorbetter-auth: 1.6.12 (regression triggered by >= 1.6.11)- ZenStack ORM 3.x, provider sqlite/postgresql
Repro
- Use
zenstackAdapteras the better-authdatabase. - Enable the
deviceAuthorizationplugin. - Sign in, then open
GET /device?user_code=...(verify step). - Error:
Invalid update args for model "DeviceCode": Validation error: At least one unique field or field set must be set at "where"
Root cause
better-auth >=1.6.11 added a verify-time ownership claim that updates with a compound where { id, status: "pending", userId: null } (https://github.com/better-auth/better-auth/blob/a6f38c72ee3423ae80b0595fec3b4a61158c374d/packages/better-auth/src/plugins/device-authorization/routes.ts#L144-L154).
The adapter's convertWhereClause() turns >=2 conditions into { AND: [...] } (https://github.com/zenstackhq/zenstack/blob/f41a1f6e4ae08af29bff3d2b3d8cde980708c214/packages/auth-adapters/better-auth/src/adapter.ts#L47-L90), and update() calls modelDb.update({ where }) unconditionally (https://github.com/zenstackhq/zenstack/blob/f41a1f6e4ae08af29bff3d2b3d8cde980708c214/packages/auth-adapters/better-auth/src/adapter.ts#L146-L152). ORM update() rejects the nested unique.
Suggested fix
In update(), when the converted where is not a single top-level unique selector, fall back to the existing updateMany() (then optionally re-read by the unique field) — mirroring how better-auth's own Prisma adapter handles non-unique update where. The adapter already implements updateMany() right below update().
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 157
- Avg merge
- 11h 42m
- Merged PRs (30d)
- 20
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from zenstackhq/zenstack
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
zenstackhq/zenstack#2873 ·
Maintainers usually reply within 1 day
-
runtime
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
zenstackhq/zenstack#2868 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 68/100
zenstackhq/zenstack#2659 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
zenstackhq/zenstack#2542 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 62/100
zenstackhq/zenstack#2296 ·
Maintainers usually reply within 1 day
All issues in zenstackhq/zenstack
Similar issues
-
submodule-pointer-regression
Difficulty 1/5 Under an hour Newbie friendliness 72/100
smith-horn/skillsmith#3061 ·
Maintainers usually reply within 1 day
-
area: ops type: test
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
accensa/x402-facilitator-stellar#559 ·
Maintainers usually reply within 1 day
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
cosimochellini/one-piece-zero-spoiler#551 ·
Maintainers usually reply within 1 day
-
getWatched() omits __proto__ directories when cwd is setPossibly taken @maxazure claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
-
area:web enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day