I see that users are getting the following error in my app. The problem is that the stacktrace doesn't lead to the point of origin in my app. Although I highly suspect it is a certain custom text field (Code below) that causes the error. Since I cannot reproduce the error on my own, I wonder if someone has some tips on how to investigate such issues in general or tips on this specific crash.

Code causing issues (likely, not certain)

@Composable
fun PINTextField(
    value: String,
    onValueChange: (String) -> Unit,
    pinLength: Int,
    allowedCharacters: (Char) -> Boolean,
    modifier: Modifier = Modifier,
    hint: String? = null,
    enabled: Boolean = true,
    errorText: String? = null,
    boxSize: Dp = 40.dp,
    boxSpacing: Dp = 12.dp,
    backgroundColor: Color = Theme.colors.surface,
    borderColor: Color = Theme.colors.border,
    focusedBorderColor: Color = Theme.colors.primary,
    errorColor: Color = Theme.colors.error,
    textColor: Color = Theme.colors.onBackground,
    cornerRadius: Dp = 14.dp,
    borderWidth: Dp = 2.dp
) {
    var textFieldValue by remember {
        mutableStateOf(TextFieldValue(value, TextRange(value.length)))
    }
    var isFocused by remember { mutableStateOf(false) }

    LaunchedEffect(value) {
        if (textFieldValue.text != value) {
            textFieldValue = TextFieldValue(value.toUpperCase(Locale.current), TextRange(value.length))
        }
    }


    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        if (hint != null) {
            Text(
                text = hint,
                style = Theme.typography.hint(),
                color = Theme.colors.onBackground,
                fontWeight = FontWeight.Medium
            )
            Height(8.dp)
        }

        BasicTextField(
            value = textFieldValue,
            onValueChange = { newValue ->
                if (newValue.text.length <= pinLength && newValue.text.all(allowedCharacters)) {
                    textFieldValue = newValue
                    onValueChange(newValue.text.toUpperCase(Locale.current))
                }
            },
            modifier = Modifier.onFocusChanged { focusState ->
                isFocused = focusState.isFocused
            },
            enabled = enabled,
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
            singleLine = true,
            textStyle = TextStyle(color = Color.Transparent), // Hide the actual text
            decorationBox = { _ ->
                Row(
                    horizontalArrangement = Arrangement.spacedBy(boxSpacing),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    repeat(pinLength) { index ->
                        val currentFieldFocused = textFieldValue.selection.start == index && isFocused
                        val hasChar = index < value.length
                        val char = if (hasChar) value[index].toString() else ""

                        val currentBorderColor = when {
                            errorText != null -> errorColor
                            !enabled -> borderColor
                            currentFieldFocused -> focusedBorderColor
                            hasChar -> focusedBorderColor
                            else -> borderColor
                        }

                        Box(
                            modifier = Modifier
                                .size(boxSize)
                                .clip(RoundedCornerShape(cornerRadius))
                                .background(backgroundColor)
                                .border(
                                    borderWidth,
                                    currentBorderColor,
                                    RoundedCornerShape(cornerRadius)
                                ),
                            contentAlignment = Alignment.Center
                        ) {
                            Text(
                                text = char,
                                style = Theme.typography.body1(),
                                color = textColor,
                                fontSize = 16.sp,
                                fontWeight = FontWeight.Medium
                            )
                        }
                    }
                }
            }
        )

        if (errorText != null) {
            Height(8.dp)
            Text(
                text = errorText,
                style = Theme.typography.body2(),
                color = Theme.colors.error,
                fontSize = 14.sp
            )

        }
    }



}

The crash stacktrace

Fatal Exception: java.lang.IllegalStateException: Required value was null.
       at androidx.compose.foundation.internal.InlineClassHelperKt.throwIllegalStateExceptionForNullCheck(InlineClassHelper.kt:30)
       at androidx.compose.foundation.internal.InlineClassHelperKt.checkPreconditionNotNull(InlineClassHelper.kt:86)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager._get_contextMenuAreaModifier_$lambda$1(TextFieldSelectionManager.kt:233)
       at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode.contentBounds(TextContextMenuToolbarHandlerModifier.kt:204)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.calculateBoundsInRoot(AndroidTextContextMenuToolbarProvider.android.kt:223)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeAndGetBounds$lambda$7(AndroidTextContextMenuToolbarProvider.android.kt:219)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeReadsAndGet$lambda$8(AndroidTextContextMenuToolbarProvider.android.kt:237)
       at androidx.compose.runtime.snapshots.Snapshot.enter(Snapshot.java:151)
       at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:528)
       at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:464)
       at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:248)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeReadsAndGet$lambda$8(AndroidTextContextMenuToolbarProvider.android.kt:237)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeReadsAndGet(AndroidTextContextMenuToolbarProvider.android.kt:237)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeAndGetBounds$lambda$7(AndroidTextContextMenuToolbarProvider.android.kt:219)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.observeAndGetBounds(AndroidTextContextMenuToolbarProvider.android.kt:219)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.createActionModeCallback$lambda$5(AndroidTextContextMenuToolbarProvider.android.kt:209)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider$TextActionModeCallbackImpl.onGetContentRect(AndroidTextContextMenuToolbarProvider.android.kt:249)
       at androidx.compose.foundation.text.contextmenu.internal.FloatingTextActionModeCallback.onGetContentRect(AndroidTextContextMenuToolbarProvider.android.kt:398)
       at com.android.internal.policy.DecorView$ActionModeCallback2Wrapper.onGetContentRect(DecorView.java:2966)
       at com.android.internal.view.FloatingActionMode.invalidateContentRect(FloatingActionMode.java:154)
       at com.android.internal.view.FloatingActionMode.invalidate(FloatingActionMode.java:149)
       at com.android.internal.policy.DecorView.setHandledFloatingActionMode(DecorView.java:2181)
       at com.android.internal.policy.DecorView.setHandledActionMode(DecorView.java:2021)
       at com.android.internal.policy.DecorView.startActionMode(DecorView.java:940)
       at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:895)
       at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1044)
       at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1044)
       at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1044)
       at android.view.View.startActionMode(View.java:7882)
       at androidx.compose.foundation.text.contextmenu.internal.TextToolbarHelperApi23.startActionMode(AndroidTextContextMenuToolbarProvider.android.kt:350)
       at androidx.compose.foundation.text.contextmenu.internal.TextToolbarHelper.startActionMode(AndroidTextContextMenuToolbarProvider.android.kt:329)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider$showTextContextMenu$2.invokeSuspend(AndroidTextContextMenuToolbarProvider.android.kt:176)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider$showTextContextMenu$2.invoke(AndroidTextContextMenuToolbarProvider.android.kt:2)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider$showTextContextMenu$2.invoke(AndroidTextContextMenuToolbarProvider.android.kt:1)
       at androidx.compose.foundation.MutatorMutex$mutate$2.invokeSuspend(MutatorMutex.kt:127)
       at androidx.compose.foundation.MutatorMutex$mutate$2.invoke(MutatorMutex.kt:2)
       at androidx.compose.foundation.MutatorMutex$mutate$2.invoke(MutatorMutex.kt:1)
       at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndspatched(Undispatched.kt:66)
       at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:43)
       at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:286)
       at androidx.compose.foundation.MutatorMutex.mutate(MutatorMutex.kt:120)
       at androidx.compose.foundation.MutatorMutex.mutate$default(MutatorMutex.kt:117)
       at androidx.compose.foundation.text.contextmenu.internal.AndroidTextContextMenuToolbarProvider.showTextContextMenu(AndroidTextContextMenuToolbarProvider.android.kt:156)
       at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invokeSuspend(TextContextMenuToolbarHandlerModifier.kt:183)
       at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invoke(TextContextMenuToolbarHandlerModifier.kt:2)
       at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invoke(TextContextMenuToolbarHandlerModifier.kt:1)
       at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:20)
       at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:360)
       at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:134)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:53)
       at kotlinx.coroutines.BuildersKt.launch(Builders.kt:1)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:44)
       at kotlinx.coroutines.BuildersKt.launch$default(Builders.kt:1)
       at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode.show(TextContextMenuToolbarHandlerModifier.kt:180)
       at androidx.compose.foundation.text.contextmenu.modifier.ToolbarRequesterImpl.show(TextContextMenuToolbarHandlerModifier.kt:68)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager.showSelectionToolbar$foundation_release(TextFieldSelectionManager.kt:959)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager.updateFloatingToolbar(TextFieldSelectionManager.kt:949)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager.access$getDragBeginSelection$p(TextFieldSelectionManager.kt:83)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager.access$updateFloatingToolbar(TextFieldSelectionManager.kt:83)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager$touchSelectionObserver$1.onEnd(TextFieldSelectionManager.kt:398)
       at androidx.compose.foundation.text.selection.TextFieldSelectionManager$touchSelectionObserver$1.onStop(TextFieldSelectionManager.kt:391)
       at androidx.compose.foundation.text.selection.SelectionGesturesKt.touchSelection(SelectionGestures.kt:137)
       at androidx.compose.foundation.text.selection.SelectionGesturesKt.access$touchSelectionSubsequentPress(SelectionGestures.kt:1)
       at androidx.compose.foundation.text.selection.SelectionGesturesKt.access$touchSelection(SelectionGestures.kt:1)
       at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$1.invokeSuspend(SelectionGestures.kt:11)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
       at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:163)
       at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:152)
       at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:470)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$kotlinx_coroutines_core(CancellableContinuationImpl.kt:504)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$kotlinx_coroutines_core$default(CancellableContinuationImpl.kt:493)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:359)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:829)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent(SuspendingPointerInputFilter.kt:699)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:725)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:436)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:422)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:422)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:422)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:422)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:422)
       at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:275)
       at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:171)
       at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:118)
       at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:2428)
       at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:2378)
       at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:2249)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3201)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3201)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3201)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)

       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3201)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
       at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:510)
       at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1968)
       at android.app.Activity.dispatchTouchEvent(Activity.java:4414)
       at curtains.internal.WindowCallbackWrapper$dispatchTouchEvent$dispatch$1.invoke(WindowCallbackWrapper.kt:58)
       at curtains.internal.WindowCallbackWrapper$dispatchTouchEvent$dispatch$1.invoke(WindowCallbackWrapper.kt:52)
       at com.posthog.android.replay.PostHogReplayIntegration.onTouchEventListener$lambda$7(PostHogReplayIntegration.kt:240)
       at curtains.internal.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.kt:65)
       at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:468)
       at android.view.View.dispatchPointerEvent(View.java:15985)
       at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7468)
       at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:7243)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6653)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6710)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6676)
       at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6841)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6684)
       at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6898)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6657)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6710)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6676)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6684)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6657)
       at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9787)
       at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9734)
       at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9676)
       at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9938)
       at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:272)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loopOnce(Looper.java:194)
       at android.os.Looper.loop(Looper.java:338)
       at android.app.ActivityThread.main(ActivityThread.java:8470)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1064)

1 Reply 1

This matches this issue, which has some Googly advice in its comments.

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.