wasmerio/wasmer · error

Function::call_async futures cannot be polled recursively fr

Error message

Function::call_async futures cannot be polled recursively from within another imported function. If you need to await a recursive call_async, consider spawning the future into your async runtime and awaiting the resulting task; e.g. tokio::task::spawn(func.call_async(...)).await

What it means

Error "Function::call_async futures cannot be polled recursively from within another imported function. If you need to await a recursive call_async, consider spawning the future into your async runtime and awaiting the resulting task; e.g. tokio::task::spawn(func.call_async(...)).await" thrown in wasmerio/wasmer.

Source

Thrown at lib/api/src/backend/sys/async_runtime.rs:266

            // We always need to acquire a new write lock on the store.
            let store_guard = store.inner.write().await;
            unsafe { crate::StoreContext::install_async(store_guard) }
        }
        _ => {
            // If we're already in a store context, it is unsafe to reuse
            // the existing store ref since it'll also be accessible from
            // the imported function that tried to poll us, which is a
            // double mutable borrow.
            // Note to people who discover this code: this *would* be safe
            // if we had a separate variation of call_async that just
            // used the existing coroutine context instead of spawning a
            // new coroutine. However, the current call_async always spawns
            // a new coroutine, so we can't allow this; every coroutine
            // needs to own its write lock on the store to make sure there
            // are no overlapping mutable borrows. If this is something
            // you're interested in, feel free to open a GitHub issue outlining
            // your use-case.
            panic!(
                "Function::call_async futures cannot be polled recursively \
                from within another imported function. If you need to await \
                a recursive call_async, consider spawning the future into \
                your async runtime and awaiting the resulting task; \
                e.g. tokio::task::spawn(func.call_async(...)).await"
            );
        }
    }
}

pub enum AsyncRuntimeError {
    YieldOutsideAsyncContext,
    RuntimeError(RuntimeError),
}

pub(crate) fn block_on_host_future<Fut>(future: Fut) -> Result<Vec<Value>, AsyncRuntimeError>
where
    Fut: Future<Output = Result<Vec<Value>, RuntimeError>> + 'static,

View on GitHub (pinned to 8c4b9ee9d3)

When it happens

Trigger: Thrown at lib/api/src/backend/sys/async_runtime.rs:266 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/29f7d6f897c03275. Report an issue: GitHub.