Skip to content

Crash on long-press text selection / paste menu with latest Compose: ClipboardUtils.hasText() fails with AndroidRichTextClipboardManager #744

Description

@eshan-gr

@MohamedRejeb

When long-pressing inside BasicRichTextEditor to open the text selection toolbar (Paste / Copy / Select All), the app crashes.

The crash occurs consistently when holding text inside the editor.

Environment
RichEditor: 1.0.0-rc14
Compose BOM: "2026.06.00"
Android: reproducible on latest Android SDKs
Kotlin: 2.0.4
Crash
FATAL EXCEPTION: main

java.lang.IllegalArgumentException:
Extracting native reference is only supported from
androidx.compose.ui.platform.AndroidClipboard instances but received
com.mohamedrejeb.richeditor.clipboard.AndroidRichTextClipboardManager

at androidx.compose.ui.platform.AndroidClipboard_androidKt.getNativeClipboardManager(AndroidClipboard.android.kt:28)
at androidx.compose.foundation.internal.ClipboardUtils.hasText(ClipboardUtils.android.kt:78)```

My code inside chat box:

```kt
BasicRichTextEditor(
                state = richTextState,
                enabled = sessionState is ChatSessionState.Ready,
                modifier = Modifier.weight(1f),
                textStyle = TextStyle(
                    fontSize = 16.sp,
                    color = if (isDark) white else Color.Black
                ),
                keyboardOptions = KeyboardOptions(
                    capitalization = KeyboardCapitalization.Sentences,
                    autoCorrect = true,
                    keyboardType = KeyboardType.Text,
                    imeAction = ImeAction.Default
                ),
                keyboardActions = KeyboardActions(onSend = {
                    val rawMarkdown = richTextState.toMarkdown()
                    if (rawMarkdown.isNotBlank()) {
                        onSendChatClickListener(rawMarkdown)
                        performReset()
                    }
                }),
                interactionSource = interactionSource,
                cursorBrush = SolidColor(if (isDark) white else JadeGreen),
                decorationBox = { innerTextField ->
........

I verified that the app-level clipboard is still Compose's default clipboard:
val clipboard = LocalClipboard.current

LaunchedEffect(Unit) {
    Log.d("Clipboard", clipboard::class.java.name)
}```
Output -> androidx.compose.ui.platform.AndroidClipboardImpl

The crash only occurs when opening the text selection / paste menu via long press.

Complete Stack trace:

AndroidRuntime          com.package        FATAL EXCEPTION: main
Process: com.package, PID: 28928
java.lang.IllegalArgumentException: Extracting native reference is only supported from androidx.compose.ui.platform.AndroidClipboard instances but received com.mohamedrejeb.richeditor.clipboard.AndroidRichTextClipboardManager
	at androidx.compose.ui.platform.AndroidClipboard_androidKt.getNativeClipboardManager(AndroidClipboard.android.kt:28)
	at androidx.compose.foundation.internal.ClipboardUtils.hasText(ClipboardUtils.android.kt:78)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager_androidKt.hasAvailableTextToPaste(TextFieldSelectionManager.android.kt:139)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager.updateClipboardEntry$foundation(TextFieldSelectionManager.kt:827)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager$contextMenuAreaModifier$2.invokeSuspend(TextFieldSelectionManager.kt:241)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager$contextMenuAreaModifier$2.invoke(Unknown Source:8)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager$contextMenuAreaModifier$2.invoke(Unknown Source:2)
	at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invokeSuspend(TextContextMenuToolbarHandlerModifier.kt:205)
	at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invoke(Unknown Source:8)
	at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode$show$1.invoke(Unknown Source:4)
	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(Unknown Source:1)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:44)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
	at androidx.compose.foundation.text.contextmenu.modifier.TextContextMenuToolbarHandlerNode.show(TextContextMenuToolbarHandlerModifier.kt:203)
	at androidx.compose.foundation.text.contextmenu.modifier.ToolbarRequesterImpl.show(TextContextMenuToolbarHandlerModifier.kt:79)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager.showSelectionToolbar$foundation(TextFieldSelectionManager.kt:1076)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager.updateFloatingToolbar(TextFieldSelectionManager.kt:1066)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager.access$updateFloatingToolbar(TextFieldSelectionManager.kt:93)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager$touchSelectionObserver$1.onEnd(TextFieldSelectionManager.kt:428)
	at androidx.compose.foundation.text.selection.TextFieldSelectionManager$touchSelectionObserver$1.onStop(TextFieldSelectionManager.kt:420)
	at androidx.compose.foundation.text.selection.SelectionGesturesKt.touchSelectionFirstPress(SelectionGestures.kt:157)
	at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelectionFirstPress$1.invokeSuspend(Unknown Source:13)
	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:445)
	at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:431)
	at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:431)
	at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:431)
	at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:431)
	at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:431)
	at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:285)
	at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:182)
	at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:116)
	at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:2864)
	at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:2804)
	at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:2625)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
	at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:502)
	at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1890)
	at android.app.Activity.dispatchTouchEvent(Activity.java:4196)
	at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:460)
	at android.view.View.dispatchPointerEvent(View.java:14799)
	at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6347)
	at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6148)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5626)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5814)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5871)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8562)
	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8513)
	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8482)
	at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8685)
	at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:259)
	at android.os.MessageQueue.nativePollOnce(Native Method)
	at android.os.MessageQueue.next(MessageQueue.java:335)
	at android.os.Looper.loopOnce(Looper.java:161)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7839)
	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:1003)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@94636b8, androidx.compose.runtime.BroadcastFrameClock@1e18c91, StandaloneCoroutine{Cancelling}@f0337f6, AndroidUiDispatcher@daff7f7]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions