Skip to content

[BUG] CreateIntentResult.Failure is silently discarded when returned before the PaymentSheet transition completes #14248

Description

@hjdealba96

Summary

When CreateIntentCallback.onCreateIntent returns a CreateIntentResult.Failure quickly — without suspending on any I/O — the sheet discards it. No error is shown, displayMessage never appears, and the sheet returns to the payment form as if nothing happened. The callback is never told the message was dropped.

Adding an artificial delay() before returning the Failure makes the message appear reliably. In our testing yield() and delay(1) were both too short; ~300ms was the threshold at which the message consistently rendered.

This only affects failures decided locally. Any path that awaits a network call before returning is slow enough that the problem never appears, which is likely why it isn't commonly hit. In our case we reject certain payment methods ourselves, based on details we can only inspect after the user has already chosen one — that decision needs no network call, which is exactly the fast path that gets dropped.

Impact: the user taps the primary button, returns to the sheet, and sees nothing at all. It reads as a broken app. We currently ship a 500ms delay purely to make our own error message visible, which is a timing guess against SDK internals rather than anything documented.

Code to reproduce

override suspend fun onCreateIntent(
    paymentMethod: PaymentMethod,
    shouldSavePaymentMethod: Boolean,
): CreateIntentResult {
    // Decided locally — no suspension before returning.
    if (isUnacceptable(paymentMethod)) {
        return CreateIntentResult.Failure(
            cause = IllegalStateException("Unsupported funding"),
            displayMessage = "This card can't be used. Please choose another.",
        )
    }
    // ...normal path: awaits a network call, and always displays correctly
}

The sheet is configured with PaymentSheet.IntentConfiguration, Mode.Setup(setupFutureUse = OnSession), and presented via presentWithIntentConfiguration.

Observed: no message, sheet returns to the form.
Expected: displayMessage is shown, as it is when the same Failure is returned after a network round trip.

Workaround: delay(500.milliseconds) immediately before returning the Failure.

Android version

Not tied to a specific OS version — it appears to be a race against the sheet's own transition animation, so a slower device makes it more likely. Reproduced consistently on our debug builds.

Impacted devices

Not device-specific.

Installation method

Gradle dependency.

Dependency Versions

kotlin: 2.4.10
stripe-android: 23.16.0
Android Gradle Plugin: 9.3.1
Gradle: 9.7.1

SDK classes

PaymentSheet, CreateIntentCallback, CreateIntentResult.Failure, PaymentSheet.IntentConfiguration

Other information

compileSdk 37, minSdk 28.

Either behaviour would be fine for us, as long as it is deterministic: queue the failure until the sheet is ready to display it, or surface a signal that it was dropped. As it stands, a correct integration can silently show the user nothing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions