diff --git a/.changeset/violet-insects-ring.md b/.changeset/violet-insects-ring.md new file mode 100644 index 00000000000..e011f401508 --- /dev/null +++ b/.changeset/violet-insects-ring.md @@ -0,0 +1,5 @@ +--- +'@clerk/elements': patch +--- + +Display hard to catch errors inside the sign-in verification step during development (when `NODE_ENV` is set to `development`). diff --git a/packages/elements/src/internals/machines/sign-in/verification.machine.ts b/packages/elements/src/internals/machines/sign-in/verification.machine.ts index 4846322a9e1..eab8a60ccfe 100644 --- a/packages/elements/src/internals/machines/sign-in/verification.machine.ts +++ b/packages/elements/src/internals/machines/sign-in/verification.machine.ts @@ -142,6 +142,16 @@ const SignInVerificationMachine = setup({ }; }, ), + setConsoleError: ({ event }) => { + if (process.env.NODE_ENV === 'development') { + assertActorEventError(event); + + throw new ClerkElementsRuntimeError(`Unable to fulfill the prepare or attempt request for the sign-in verification. +Error: ${event.error.message} + +Please open an issue if you continue to run into this issue.`); + } + }, }, guards: { isResendable: ({ context }) => context.resendable || context.resendableAfter === 0, @@ -218,7 +228,7 @@ const SignInVerificationMachine = setup({ target: 'Pending', }, onError: { - actions: 'setFormErrors', + actions: ['setFormErrors', 'setConsoleError'], target: 'Pending', }, }, @@ -316,7 +326,7 @@ const SignInVerificationMachine = setup({ actions: ['sendToNext', 'sendToLoading'], }, onError: { - actions: ['setFormErrors', 'sendToLoading'], + actions: ['setFormErrors', 'setConsoleError', 'sendToLoading'], target: 'Pending', }, }, @@ -352,14 +362,14 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ return Promise.resolve(clerk.client.signIn); } - assertIsDefined(params); + assertIsDefined(params, 'First factor params'); return await clerk.client.signIn.prepareFirstFactor(params as PrepareFirstFactorParams); }), attempt: fromPromise(async ({ input }) => { const { currentFactor, fields, parent } = input as AttemptFirstFactorInput; - assertIsDefined(currentFactor); + assertIsDefined(currentFactor, 'Current factor'); let attemptParams: AttemptFirstFactorParams; @@ -369,7 +379,7 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ switch (strategy) { case 'password': { - assertIsDefined(password); + assertIsDefined(password, 'Password'); attemptParams = { strategy, @@ -380,7 +390,7 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ } case 'reset_password_phone_code': case 'reset_password_email_code': { - assertIsDefined(code); + assertIsDefined(code, 'Code for resetting phone/email'); attemptParams = { strategy, @@ -392,7 +402,7 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ } case 'phone_code': case 'email_code': { - assertIsDefined(code); + assertIsDefined(code, 'Code for phone/email'); attemptParams = { strategy, @@ -403,7 +413,7 @@ export const SignInFirstFactorMachine = SignInVerificationMachine.provide({ } case 'web3_metamask_signature': { const signature = fields.get('signature')?.value as string | undefined; - assertIsDefined(signature); + assertIsDefined(signature, 'Web3 Metamask signature'); attemptParams = { strategy, @@ -438,7 +448,7 @@ export const SignInSecondFactorMachine = SignInVerificationMachine.provide({ const currentVerificationExpiration = clerk.client.signIn.secondFactorVerification.expireAt; const needsPrepare = resendable || !currentVerificationExpiration || currentVerificationExpiration < new Date(); - assertIsDefined(params); + assertIsDefined(params, 'Second factor params'); if (params.strategy !== 'phone_code' || !needsPrepare) { return Promise.resolve(clerk.client.signIn); @@ -454,8 +464,8 @@ export const SignInSecondFactorMachine = SignInVerificationMachine.provide({ const code = fields.get('code')?.value as string; - assertIsDefined(currentFactor); - assertIsDefined(code); + assertIsDefined(currentFactor, 'Current factor'); + assertIsDefined(code, 'Code'); return await parent.getSnapshot().context.clerk.client.signIn.attemptSecondFactor({ strategy: currentFactor.strategy,