Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[@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)

オープン
#8,684 コメント 6 件 リアクション 2 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
52/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
react, typescript

調査の方向性

事前構築された フローと、issue に記載されている signUp.create および prepareEmailAddressVerification の呼び出しから始めます。pnpm --filter web build && pnpm --filter web preview で再現し、Network パネルを確認します。カスタムの useSignUp() フローを必要とせず、1 回のサインアップ送信で検証メールが正確に 1 通生成されれば完了です。

索引モデルが issue の本文から書いたものです。

説明

Stale

Preflight

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:

  1. POST /v1/client/sign_ups?__clerk_api_version=2025-11-10 — signUp.create({ emailAddress, password })
  2. 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 from signIn.create() and becomes invalid as soon as the second one is generated. When you call signIn.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 that signUp.create() already initiated verification (returned status with the right verification primed) and skip the redundant prepareEmailAddressVerification call; 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
  1. pnpm --filter web build && pnpm --filter web preview (prod-build, no StrictMode dev-time side effects)
  2. Open the preview URL, navigate to /sign-up
  3. DevTools → Network tab → filter clerk. → clear log
  4. Enter a fresh email + valid password, click Continue
  5. 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

主要言語
TypeScript
スター
1.8k
フォーク
472
平均マージ
2日 12時間
マージ済み PR(30日)
222

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

clerk/javascript のほかの issue

clerk/javascript の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。