diff --git a/.changeset/brave-mammals-burn.md b/.changeset/brave-mammals-burn.md new file mode 100644 index 00000000000..233a8b48ddb --- /dev/null +++ b/.changeset/brave-mammals-burn.md @@ -0,0 +1,5 @@ +--- +'@clerk/ui': patch +--- + +Fix the payment method form getting stuck in a loading state after a failed card setup. Non-validation errors such as 3DS authentication failures are now displayed. diff --git a/packages/ui/src/components/PaymentMethods/AddPaymentMethod.tsx b/packages/ui/src/components/PaymentMethods/AddPaymentMethod.tsx index a0ef7a64b28..1559bfa620b 100644 --- a/packages/ui/src/components/PaymentMethods/AddPaymentMethod.tsx +++ b/packages/ui/src/components/PaymentMethods/AddPaymentMethod.tsx @@ -206,7 +206,14 @@ const AddPaymentMethodForm = ({ children }: PropsWithChildren) => { const { data, error } = await submitPaymentElement(); if (error) { - return; // just return, since stripe will handle the error + card.setIdle(); + // Validation errors are already rendered inline by Stripe's PaymentElement. + // Non-validation errors (e.g. 3DS authentication failure) are not surfaced by + // Stripe's UI, so we display them ourselves. + if (error.error.type !== 'validation_error') { + card.setError(error.error.message); + } + return; } try { await onSuccess(data);