Repository: stripe/stripe-android

Issue #8625: [BUG] CardBrandView change to Composable causes app crashes
Created: 2024-06-13T19:30:51Z
Summary
This issue is a weird one in that it can be traced back to the Stripe Android SDK but only manifests itself within React Native. The issue at play affects both Stripe's React Native SDK as well as our Olo Pay React Native SDK, both of which are built on top of Stripe's Android SDK.
It appears that CardBrandView was changed in v20.36.0 to be a Composable as part of the Card Brand Choice feature. This change affects CardInputWidget, CardMultilineWidget, and CardFormView and causes many issues in React Native, which doesn't have great support for Jetpack Compose.
Updating to v20.36.0 or later caused issues that we had never seen before:

App crashes
Card brand icon completely disappears and stops rendering (likely due to this issue)

These issues occur in our React Native SDK, which is built on top of our Android SDK, and have been traced back to Stripe's Android SDK implementation, specifically related to using a Composable inside normal views.
Stripe's own React Native SDK is also affected by this, and we have found many issues in Stripe's React Native repo that others have reported that ultimately are due to this Android Composable. Here are few (this is by no means an exhaustive list):

stripe/stripe-react-native#1597
stripe/stripe-react-native#1584
stripe/stripe-react-native#1665

Android version
20.36.0 and newer
Installation method
Gradle
SDK classes

CardBrandView
CardInputWidget
CardMultilineWidget
CardFormView

Video

  
    
    

    Disappearing.Card.Brand.Icon.mov
    
  

  

  



  
    
    

    Compose.Crash.mov
    
  

  

  


Crash Stacktrace
Exception in native call
java.lang.IllegalStateException: Cannot locate windowRecomposer; View androidx.compose.ui.platform.ComposeView{3fa3229 V.E...... ......I. 0,0-0,0 #7f080153 app:id/icon} is not attached to a window
	at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:295)
	at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(ComposeView.android.kt:244)
	at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:251)
	at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:288)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:278)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at androidx.cardview.widget.CardView.onMeasure(CardView.java:260)
	at com.google.android.material.card.MaterialCardView.onMeasure(MaterialCardView.java:211)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:632)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:323)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solveHorizontalMatchConstraint(Direct.java:709)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:374)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solvingPass(Direct.java:144)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:693)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:160)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:291)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:632)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:323)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solveHorizontalMatchConstraint(Direct.java:709)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:374)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solvingPass(Direct.java:144)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:693)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:160)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:291)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at com.facebook.react.uimanager.NativeViewHierarchyManager.updateLayout(NativeViewHierarchyManager.java:189)
	at com.facebook.react.uimanager.UIViewOperationQueue$UpdateLayoutOperation.execute(UIViewOperationQueue.java:169)
	at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:915)
	at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1026)
	at com.facebook.react.uimanager.UIViewOperationQueue.access$2600(UIViewOperationQueue.java:47)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1086)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
	at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
	at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
	at android.view.Choreographer.doCallbacks(Choreographer.java:899)
	at android.view.Choreographer.doFrame(Choreographer.java:827)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
	at android.os.Handler.handleCallback(Handler.java:942)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7872)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Duplicate issue #8419: [BUG] App crash: IllegalStateException: Cannot locate windowRecomposer; View androidx.compose.ui.platform.ComposeView
Created: 2024-05-06T11:33:11Z
I need to implement the co-badged-card requirements on the CardInputWidget, so I need to move from 20.28.3 to 20.37.4.
After upgrading, my app just crashes. Note that I am not using Jetpack Compose, and I cannot migrate my codebase to it at the moment.
My layout is created dynamically and I am using Stripe's com.stripe.android.view.CardInputWidget. So, to simplify, let's say my CardInputWidget is inside a FrameLayout.
Is there any way to make it work in versions 20.37.4 and up, without using Compose views?
In case it helps, this is the crash log:
FATAL EXCEPTION: main Process: <my_package_id>, PID: 12424 java.lang.IllegalStateException: Cannot locate windowRecomposer; View androidx.compose.ui.platform.ComposeView{9ce30d7 V.E...... ......I. 0,0-0,0 #7f0901fe app:id/icon} is not attached to a window at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:295) at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(ComposeView.android.kt:244) at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:251) at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:288) at android.view.View.measure(View.java:26357) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981) at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) at android.view.View.measure(View.java:26357) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608) at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1240) at android.widget.LinearLayout.onMeasure(LinearLayout.java:723) at android.view.View.measure(View.java:26357) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981) at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) at android.view.View.measure(View.java:26357) at com.google.android.flexbox.FlexboxHelper.calculateFlexLines(FlexboxHelper.java:477) at com.google.android.flexbox.FlexboxHelper.calculateHorizontalFlexLines(FlexboxHelper.java:249) at com.google.android.flexbox.FlexboxLayoutManager.updateFlexLines(FlexboxLayoutManager.java:960) at com.google.android.flexbox.FlexboxLayoutManager.onLayoutChildren(FlexboxLayoutManager.java:737) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4645) at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4348) at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4919) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:689) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213) at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899) at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1263) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729) at android.widget.LinearLayout.onLayout(LinearLayout.java:1638) 2024-05-06 13:02:15.551 12424-12424 AndroidRuntime          <my_package_id>          E  	at android.view.View.layout(View.java:23693) (Ask Gemini) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729) at android.widget.LinearLayout.onLayout(LinearLayout.java:1638) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at com.android.internal.policy.DecorView.onLayout(DecorView.java:799) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3999) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3372) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2328) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9087) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239) at android.view.Choreographer.doCallbacks(Choreographer.java:899) at android.view.Choreographer.doFrame(Choreographer.java:832) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Closing comment (2024-06-18T16:42:42Z): I'm going to close this as a duplicate of #8625
I realize this isn't fixed yet, and I apologize for that. We will work on a path forward and update the other issue when we have something to share.