Skip to content

wasmJs: The operation was aborted. #2860

Closed as not planned
Closed as not planned
@julius-b

Description

@julius-b

Describe the bug
I'm not certain but I think there is a problem with Coil and the way it acts when the image loading is cancelled by AsyncImage moving out of scope, specifically on wasmJs. Using the circuit navigation library, when changing the Screen (effectively the @Composable) from a LaunchedEffect while the current AsyncImage is still loading, this exception occurs (app/website crash):

Uncaught runtime errors:
ERROR
The operation was aborted. 
io.ktor.client.fetch.abort_$external_fun@webpack-internal:///./kotlin/composeApp.uninstantiated.mjs:4645:73
<CoilBug:composeApp>.io.ktor.client.engine.js.JsClientEngine$execute$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[59948]:0x761a81
<CoilBug:composeApp>.io.ktor.client.engine.js.JsClientEngine$execute$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[59949]:0x761aa9
<CoilBug:composeApp>.kotlinx.coroutines.InvokeOnCancelling.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15857]:0x3c6146
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.notifyCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15773]:0x3c33df
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15816]:0x3c53e1
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCompleting@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15815]:0x3c5202
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelMakeCompleting@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15806]:0x3c495c
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelImpl@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15805]:0x3c4847
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelInternal@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15801]:0x3c47c1
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancel@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15798]:0x3c46ed
<CoilBug:composeApp>.io.ktor.client.engine.createCallContext$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[58743]:0x749a64
<CoilBug:composeApp>.io.ktor.client.engine.createCallContext$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[58744]:0x749a8d
<CoilBug:composeApp>.kotlinx.coroutines.InvokeOnCancelling.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15857]:0x3c6146
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.notifyCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15773]:0x3c33df
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15812]:0x3c4fed
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.makeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15810]:0x3c4e5b
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelImpl@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15805]:0x3c4865
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.parentCancelled@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15802]:0x3c47d7
<CoilBug:composeApp>.kotlinx.coroutines.ChildHandleNode.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15867]:0x3c62c8
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.notifyCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15773]:0x3c33df
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15812]:0x3c4fed
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.makeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15810]:0x3c4e5b
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelImpl@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15805]:0x3c4865
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.parentCancelled@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15802]:0x3c47d7
<CoilBug:composeApp>.kotlinx.coroutines.ChildHandleNode.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15867]:0x3c62c8
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.notifyCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15773]:0x3c33df
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15812]:0x3c4fed
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.makeCancelling@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15810]:0x3c4e5b
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelImpl@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15805]:0x3c4865
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelInternal@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15801]:0x3c47c1
<CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancel@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15798]:0x3c46ed
<CoilBug:composeApp>.kotlinx.coroutines.Job.cancel$default@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[15629]:0x3c0e05
<CoilBug:composeApp>.coil3.compose.AsyncImagePainter.<set-rememberJob>@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[54479]:0x6f7de0
<CoilBug:composeApp>.coil3.compose.AsyncImagePainter.onForgotten@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[54509]:0x6f8232
<CoilBug:composeApp>.coil3.compose.internal.ContentPainterNode.onDetach@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[54661]:0x6fb8c2
<CoilBug:composeApp>.androidx.compose.ui.Node.runDetachLifecycle@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[33895]:0x53c2d1
<CoilBug:composeApp>.androidx.compose.ui.node.NodeChain.runDetachLifecycle@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37874]:0x59b6a2
<CoilBug:composeApp>.androidx.compose.ui.node.LayoutNode.detach@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37095]:0x587d6d
<CoilBug:composeApp>.androidx.compose.ui.node.LayoutNode.detach@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37095]:0x587def
<CoilBug:composeApp>.androidx.compose.ui.node.LayoutNode.detach@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37095]:0x587def
<CoilBug:composeApp>.androidx.compose.ui.node.LayoutNode.onChildRemoved@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37088]:0x587382
<CoilBug:composeApp>.androidx.compose.ui.node.LayoutNode.removeAt@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[37086]:0x58728d
<CoilBug:composeApp>.androidx.compose.ui.platform.DefaultUiApplier.remove@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[40207]:0x5be628
<CoilBug:composeApp>.androidx.compose.runtime.changelist.RemoveNode.execute@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[23286]:0x4425a8
<CoilBug:composeApp>.androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[23451]:0x445e15
<CoilBug:composeApp>.androidx.compose.runtime.changelist.ChangeList.executeAndFlushAllPendingChanges@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[23043]:0x4384da
<CoilBug:composeApp>.androidx.compose.runtime.CompositionImpl.applyChangesInLocked@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[21704]:0x41440e
<CoilBug:composeApp>.androidx.compose.runtime.CompositionImpl.applyChanges@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[21705]:0x414a1d
<CoilBug:composeApp>.androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$slambda$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[22044]:0x41e59b
<CoilBug:composeApp>.androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$slambda$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[22045]:0x41ed2e
<CoilBug:composeApp>.androidx.compose.runtime.FrameAwaiter.resume@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[21102]:0x401dc4
<CoilBug:composeApp>.androidx.compose.runtime.BroadcastFrameClock.sendFrame@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[21120]:0x402476
<CoilBug:composeApp>.androidx.compose.ui.scene.BaseComposeScene.render@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[40650]:0x5c5b05
<CoilBug:composeApp>.androidx.compose.ui.window.<no name provided>.onRender@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[41315]:0x5d254f
<CoilBug:composeApp>.org.jetbrains.skiko.<no name provided>.drawFrame@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[28896]:0x4c4d98
<CoilBug:composeApp>.org.jetbrains.skiko.CanvasRenderer$needRedraw$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[28863]:0x4c4718
<CoilBug:composeApp>.org.jetbrains.skiko.CanvasRenderer$needRedraw$lambda.invoke@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[28864]:0x4c4771
<CoilBug:composeApp>.org.w3c.dom.__callFunction_((Double)->Unit)@http://localhost:8080/aa701647711f341d29ed.wasm:wasm-function[18326]:0x3f152f
org.w3c.dom.__convertKotlinClosureToJsClosure_((Double)->Unit)/<@webpack-internal:///./kotlin/composeApp.uninstantiated.mjs:1195:124

To Reproduce
Here is a very simple repository to reproduce: https://github.com/julius-b/coil-bug
It's basically just an AsyncImage: https://github.com/julius-b/coil-bug/blob/main/composeApp/src/wasmJsMain/kotlin/ch/whatever/MainScreen.kt#L69
LaunchedEffect that cancels the AsyncImage: https://github.com/julius-b/coil-bug/blob/main/composeApp/src/wasmJsMain/kotlin/ch/whatever/App.kt#L30

The demo loads 20 images which increases the chance of this bug occurring to about every 2nd page reload.
note: In this sample, the bug can be prevented by changing whether the initial screen is even shown, which makes it so that the image loading is never cancelled.

NOTE: in this demo, the bug only occurs when the QuizView (Screen) also uses AsyncImage, but in the project where I noticed this issue the QuizView does not use AsyncImage and the bug still occurs.
Also the bug is significantly rarer in Chromium (^ report was with Firefox) and the Stacktrace there is differnt:

Uncaught runtime errors:
×
ERROR
BodyStreamBuffer was aborted
AbortError: BodyStreamBuffer was aborted
    at io.ktor.client.fetch.abort_$external_fun (webpack-internal:///./kotlin/composeApp.uninstantiated.mjs:4645:73)
    at <CoilBug:composeApp>.io.ktor.client.engine.js.JsClientEngine$execute$lambda.invoke (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[59948]:0x761a81)
    at <CoilBug:composeApp>.io.ktor.client.engine.js.JsClientEngine$execute$lambda.invoke (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[59949]:0x761aa9)
    at <CoilBug:composeApp>.kotlinx.coroutines.InvokeOnCancelling.invoke (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15857]:0x3c6146)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.notifyCancelling (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15773]:0x3c33df)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15816]:0x3c53e1)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.tryMakeCompleting (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15815]:0x3c5202)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelMakeCompleting (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15806]:0x3c495c)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelImpl (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15805]:0x3c4847)
    at <CoilBug:composeApp>.kotlinx.coroutines.JobSupport.cancelInternal (http://localhost:8080/5bf60037f095d0dccd78.wasm:wasm-function[15801]:0x3c47c1)

(similar to #2462)

Version
coil = "3.1.0"
compose-multiplatform = "1.7.3"
kotlin = "2.1.10"
ktor = "3.0.3"

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