Skip to content

Commit 0a2dde8

Browse files
authored
fix auth adoption provider fallback (#254)
1 parent 21acedd commit 0a2dde8

18 files changed

Lines changed: 205 additions & 25 deletions

File tree

.changeset/install-kitcn-skill.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
## Patches
66

7-
- Improve agent guidance to install and use the `kitcn` skill before reading documentation.
7+
- Fix raw Convex auth adoption for TanStack Start apps that do not keep a kitcn provider at the default path.
8+
- Clarify organization auth guidance for Stripe-style plugin side effects in Convex actions.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
title: Better Auth external plugin calls need Convex actions
3+
date: 2026-04-29
4+
category: integration-issues
5+
module: auth-runtime
6+
problem_type: runtime_error
7+
component: authentication
8+
symptoms:
9+
- `ctx.auth.api.updateOrganization()` fails inside a Convex mutation when the Stripe plugin is installed.
10+
- Convex throws `Can't use setTimeout in queries and mutations`.
11+
root_cause: wrong_api
12+
resolution_type: documentation_update
13+
severity: high
14+
tags: [auth, better-auth, stripe, convex, actions]
15+
---
16+
17+
# Better Auth external plugin calls need Convex actions
18+
19+
## Problem
20+
21+
Better Auth API endpoints can run plugin hooks in addition to local database
22+
writes. When an endpoint reaches Stripe, Polar, or direct email delivery from a
23+
Convex mutation, the external SDK can call APIs such as `setTimeout` or `fetch`
24+
that Convex mutations do not allow.
25+
26+
## Symptoms
27+
28+
- `auth.api.updateOrganization()` works until `@better-auth/stripe` is present.
29+
- Convex throws `Can't use setTimeout in queries and mutations`.
30+
- The stack points into `stripe/esm/RequestSender.js` or another external SDK.
31+
32+
## What Didn't Work
33+
34+
- Treating `ctx.auth.api.*` as a safe mutation helper for every organization
35+
write. Some endpoints are DB-only in one plugin set and side-effectful in
36+
another.
37+
- Creating placeholder provider files or changing adapter write behavior. The
38+
failure happens before Convex can allow external SDK work in a mutation.
39+
40+
## Solution
41+
42+
Use mutations only for local Convex writes. Use actions for Better Auth
43+
endpoints that may run external plugin work.
44+
45+
For simple organization profile updates, stay local:
46+
47+
```ts
48+
await ctx.orm
49+
.update(organization)
50+
.set(data)
51+
.where(eq(organization.id, input.organizationId));
52+
```
53+
54+
For operations that call Stripe, Polar, or direct email delivery, expose an
55+
`authAction` and bridge back into queries or mutations through generated
56+
callers when local reads or writes are needed.
57+
58+
## Why This Works
59+
60+
Convex mutations are deterministic database transactions. External SDKs are not
61+
allowed there. Actions are the Convex function type designed for external I/O,
62+
and generated callers keep the app code typed when action code needs local data.
63+
64+
## Prevention
65+
66+
- Do not document `ctx.auth.api.*` as universally mutation-safe.
67+
- Prefer `ctx.orm` for simple reads and updates.
68+
- Use `authAction` for user-facing billing, payment, portal, email, and other
69+
SDK-backed flows.
70+
- When adding auth plugin docs, explicitly classify each example as DB-only
71+
mutation work or external-I/O action work.
72+
73+
## Related Issues
74+
75+
- `docs/solutions/integration-issues/auth-plugin-timestamp-writes-must-respect-table-schema-20260422.md`
76+
- `docs/solutions/integration-issues/raw-convex-start-auth-adoption-must-patch-start-provider-and-react-client-20260410.md`

docs/solutions/integration-issues/raw-convex-start-auth-adoption-must-patch-start-provider-and-react-client-20260410.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Raw Convex Start auth adoption must patch Start provider and React client
33
category: integration-issues
4+
last_updated: 2026-04-29
45
tags:
56
- convex
67
- auth
@@ -10,6 +11,7 @@ tags:
1011
- scaffolding
1112
symptoms:
1213
- `kitcn add auth --preset convex --yes` fails on TanStack Start with `Auth preset "convex" requires a Vite-style client entry file (main.tsx/main.jsx).`
14+
- `kitcn add auth --preset convex --yes --overwrite` fails on TanStack Start with `Auth preset "convex" for TanStack Start expects src/lib/convex/convex-provider.tsx.`
1315
- raw Convex Start auth adoption writes `process.env.NEXT_PUBLIC_CONVEX_SITE_URL!` into `src/lib/convex/auth-client.ts`
1416
- TanStack Start is detected as a supported shell, but raw auth adoption still behaves like plain Vite
1517
module: auth-adoption
@@ -35,6 +37,9 @@ Two raw-preset branches were missing for TanStack Start:
3537
2. template resolution only swapped the default Start auth client template, not
3638
the raw Convex auth client template, so Start inherited the Next
3739
`NEXT_PUBLIC_CONVEX_SITE_URL` variant
40+
3. the raw Start provider patch still treated the kitcn-init provider path as
41+
mandatory, even though raw adoption must work in apps that own provider
42+
wiring elsewhere
3843

3944
The bug was not in auth bootstrap itself. It was in scaffold selection.
4045

@@ -44,18 +49,21 @@ Keep the raw Convex preset minimal on TanStack Start.
4449

4550
Do not route Start through the richer kitcn auth scaffold. Instead:
4651

47-
1. patch `src/lib/convex/convex-provider.tsx` in place, the same way raw Next
48-
patches its provider shell
52+
1. patch `src/lib/convex/convex-provider.tsx` in place when it exists, the same
53+
way raw Next patches its provider shell
4954
2. keep the raw auth client shape with no `createAuthMutations()`
5055
3. use the React/Vite raw auth client template for Start so it reads
5156
`import.meta.env.VITE_CONVEX_SITE_URL!`
57+
4. if the Start provider file is absent, skip that patch with a manual action
58+
instead of failing the whole auth adoption
5259

5360
That preserves the raw Convex contract:
5461

5562
- no `kitcn.json`
5663
- no cRPC scaffold churn
5764
- no generated `/auth` page
5865
- no Start auth proxy route
66+
- no forced placeholder provider file just to let the command finish
5967

6068
## Verification
6169

@@ -76,7 +84,8 @@ That preserves the raw Convex contract:
7684
auth template branch too
7785
3. For raw preset adoption, patch the narrowest existing provider shell instead
7886
of replacing it with the full managed auth baseline
79-
4. Keep a dedicated bootstrap-heavy raw Start scenario so raw auth adoption
87+
4. Missing raw-provider shells should become manual actions, not hard errors
88+
5. Keep a dedicated bootstrap-heavy raw Start scenario so raw auth adoption
8089
drift fails in scenario validation, not in user migration threads
8190

8291
## Files Changed

fixtures/expo-auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"@tanstack/react-query": "5.95.2",
99
"better-auth": "1.6.9",
1010
"convex": "1.36.1",
11-
"expo": "~55.0.17",
11+
"expo": "~55.0.18",
1212
"expo-constants": "~55.0.15",
1313
"expo-device": "~55.0.15",
1414
"expo-font": "~55.0.6",

fixtures/expo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"@react-navigation/native": "^7.1.33",
77
"@tanstack/react-query": "5.95.2",
88
"convex": "1.36.1",
9-
"expo": "~55.0.17",
9+
"expo": "~55.0.18",
1010
"expo-constants": "~55.0.15",
1111
"expo-device": "~55.0.15",
1212
"expo-font": "~55.0.6",

fixtures/next-auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"convex": "1.36.1",
1010
"hono": "4.12.9",
1111
"kitcn": "workspace:*",
12-
"lucide-react": "^1.11.0",
12+
"lucide-react": "^1.14.0",
1313
"next": "16.1.7",
1414
"next-themes": "^0.4.6",
1515
"react": "^19.2.4",

fixtures/next/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"convex": "1.36.1",
99
"hono": "4.12.9",
1010
"kitcn": "workspace:*",
11-
"lucide-react": "^1.11.0",
11+
"lucide-react": "^1.14.0",
1212
"next": "16.1.7",
1313
"next-themes": "^0.4.6",
1414
"react": "^19.2.4",

fixtures/start-auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"convex": "1.36.1",
1818
"hono": "4.12.9",
1919
"kitcn": "workspace:*",
20-
"lucide-react": "^1.11.0",
20+
"lucide-react": "^1.14.0",
2121
"nitro": "latest",
2222
"react": "^19.2.4",
2323
"react-dom": "^19.2.4",

fixtures/start/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"convex": "1.36.1",
1717
"hono": "4.12.9",
1818
"kitcn": "workspace:*",
19-
"lucide-react": "^1.11.0",
19+
"lucide-react": "^1.14.0",
2020
"nitro": "latest",
2121
"react": "^19.2.4",
2222
"react-dom": "^19.2.4",

fixtures/vite-auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"convex": "1.36.1",
1212
"hono": "4.12.9",
1313
"kitcn": "workspace:*",
14-
"lucide-react": "^1.11.0",
14+
"lucide-react": "^1.14.0",
1515
"react": "^19.2.4",
1616
"react-dom": "^19.2.4",
1717
"shadcn": "latest",

0 commit comments

Comments
 (0)