[@clerk/clerk-js] <SignUp/> sends 2 verification code emails per sign-up: both POST /sign_ups and POST /prepare_verification trigger email send (Flutter analog #117)
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 52/100
- Issue-Typ
- Bug
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- react, typescript
- Bereich
- api, authentication, frontend
Rechercherichtung
Beginne mit dem vorgefertigten -Ablauf und den im Issue beschriebenen Aufrufen signUp.create und prepareEmailAddressVerification; reproduziere ihn mit pnpm --filter web build && pnpm --filter web preview und untersuche das Network-Panel. Als erledigt gilt, wenn eine einzige Sign-up-Übermittlung genau eine Verifizierungs-E-Mail erzeugt, ohne einen benutzerdefinierten useSignUp()-Ablauf zu erfordern.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Preflight
- I have looked into the Readme, Contributing docs and existing issues
- I have reviewed the documentation
Description
The prebuilt <SignUp/> widget from @clerk/react@6.4.2 sends two verification-code emails for a single sign-up submission. The Network panel shows the widget makes two POST requests during one submit, and both server endpoints trigger a verification email send:
POST /v1/client/sign_ups?__clerk_api_version=2025-11-10—signUp.create({ emailAddress, password })POST /v1/client/sign_ups/<id>/prepare_verification?__clerk_api_version=2025-11-10—signUp.prepareEmailAddressVerification({ strategy: 'email_code' })
The user receives two emails with different codes; the first one is invalidated by the second.
Why this is a real bug (not a duplicate of #887)
This is the prebuilt-widget analog of the documented behavior in #887 (closed 2023-03-03), where Clerk contributor @gkats explained:
the
signIn.create()method will also prepare a verification under the hood when called with a strategy such as "email_code". That's why you get two codes. The first one comes fromsignIn.create()and becomes invalid as soon as the second one is generated. When you callsignIn.create()with a "phone_code", "email_code" or "email_link" strategy you don't need to also prepare the verification afterwards.
That explanation applies symmetrically to signUp.create(): when the application's configured strategy is email_code (Dashboard → User & Authentication → Email, Phone, Username → Email address → ✅ Email verification code), signUp.create() auto-prepares a verification on the server side, and the widget's subsequent explicit prepareEmailAddressVerification call generates a second code.
The #887 resolution was a workaround for custom sign-in flows: omit the strategy from signIn.create(), then call prepareFirstFactor() manually. Users of the prebuilt <SignUp/> widget cannot apply this workaround — the widget controls both calls internally. Rebuilding sign-up as a custom useSignUp() flow defeats the purpose of the prebuilt component.
So either:
- (a) The prebuilt
<SignUp/>widget should detect thatsignUp.create()already initiated verification (returned status with the right verification primed) and skip the redundantprepareEmailAddressVerificationcall; OR - (b)
signUp.create()should NOT auto-prepare a verification (the widget should be the sole driver of when verification preparation happens, matching what the workaround in #887 recommends for custom flows).
For comparison, the same root-cause shape was filed against the Flutter SDK and is the documented behavior there too: clerk/clerk-sdk-flutter#117 (createSignUp + follow-up triggering two emails).
Reproduction
Minimal repro is the prebuilt <SignUp/> widget with password + email_code strategy. No custom code, no useSignUp() flow.
// main.tsx
import { ClerkProvider } from "@clerk/react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<ClerkProvider publishableKey={CLERK_KEY}>
<App />
</ClerkProvider>
</StrictMode>
);
// sign-up.tsx
import { SignUp } from "@clerk/react";
export function SignUpPage() {
return (
<SignUp
routing="path"
path="/sign-up"
signInUrl="/sign-in"
/>
);
}
Clerk Dashboard → User & Authentication → Email, Phone, Username → Email address → Verification methods:
- ✅ Email verification code
- ❌ Email verification link
(Only ONE strategy enabled. Issue reproduces regardless — not a dashboard misconfig.)
Steps
pnpm --filter web build && pnpm --filter web preview(prod-build, no StrictMode dev-time side effects)- Open the preview URL, navigate to
/sign-up - DevTools → Network tab → filter
clerk.→ clear log - Enter a fresh email + valid password, click Continue
- Observe Network panel + inbox
Observed
| Endpoint | Method | Count | Status |
|---|---|---|---|
/v1/client/sign_ups?__clerk_api_version=2025-11-10 |
POST | 1 | 200 |
/v1/client/sign_ups/<id>/prepare_verification?__clerk_api_version=2025-11-10 |
POST | 1 | 200 |
/v1/client/sign_ups/<id> |
PATCH | 0 | — |
| Verification emails received within 60s | — | 2 | first invalidated by second per #887 |
Expected
Exactly 1 verification email per sign-up submission from the prebuilt <SignUp/> widget — without requiring users to drop the widget and write a custom useSignUp() flow.
SDK / Environment
@clerk/react:^6.4.2@clerk/clerk-js(transitive, bundled with@clerk/react@6.4.2)- React:
19.0.x+react-dom@19.0.x - Build tool: Vite 5, prod build (
pnpm build && pnpm preview) - Browser: Chrome (latest stable)
- API version (from request URL):
__clerk_api_version=2025-11-10 - Dashboard strategy: Email verification code enabled; Email verification link disabled
Workaround
The workaround documented in #887 — omit strategy from the create() call, then explicitly call the prepare method — requires rebuilding sign-up as a custom useSignUp() flow. This is not viable for users of the prebuilt <SignUp/> component (the widget owns those calls).
No workaround within the prebuilt widget is known.
References
- #887 —
signIn.prepareFirstFactorsending two emails with different codes (closed 2023-03-03; sign-in side; documents the by-designcreate({strategy})auto-prepare behavior) - clerk/clerk-sdk-flutter#117 —
auth.attemptSignUptriggers two verification code emails (Flutter SDK analog of this exact symptom shape) - #4324 — Receiving Twice Email Verification Codes During Sign-In (possibly related, unresolved as of search; sign-in side,
@clerk/nextjs ^5.7.2)
- Vorherrschende Sprache
- TypeScript
- Sterne
- 1.8k
- Forks
- 472
- Ø Merge
- 2 T. 12 Std.
- Gemergte PRs (30 T.)
- 222
Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus clerk/javascript
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
clerk/javascript#9611 · 1 Kommentar ·
-
clerk/javascript#9891 · 1 zugewiesene Person ·
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 64/100
clerk/javascript#9775 · 1 Kommentar ·
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
clerk/javascript#9770 · 3 Kommentare ·
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 68/100
clerk/javascript#9667 · 1 Kommentar ·
Alle Issues in clerk/javascript
Ähnliche Issues
-
bug(cli): hapi doctor inline-media prints a fabricated B:\ helper-script path in packaged installs Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
-
Crush Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 85/100
catppuccin/catppuccin#3125 ·
-
Add a SECURITY.md Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 90/100
ElementsProject/cln-application#167 · 1 Kommentar · 1 Reaktion ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
Quantco/pnpm-licenses#17 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100