Attempting to write a wasi-http handler with a sync-lifted handler panics in guest code.
How to Reproduce
Using -export: to sync-lift a wasi:http/handler#handle export:
// async: ["-export:wasi:http/handler@0.3.0-rc-2026-03-15#handle"]
fn handle(_req: Request) -> Result<Response, ErrorCode> {
let headers = Fields::new();
let (tw, tr) = wit_future::new(|| Ok(None::<Trailers>));
drop(tw); // <-- panics
let (response, _) = Response::new(headers, None, tr);
Ok(response)
}
Results in a trap/panic in guest code.
Backtrace
thread '<unnamed>' (1) panicked at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13:
assertion failed: !task.is_null()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
worker error: error while executing at wasm backtrace:
// ... panic/abort frames ....
12: 0x4dd6 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::register_waker::hde47cb997528dce8
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13
- wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete_with_code::hd22a90f526e6d1de
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:338:18
13: 0x57a5 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete::h605a2b23cc93fc87
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:293:14
14: 0x5c81 - <wit_bindgen::rt::async_support::future_support::RawFutureWrite<O> as core::future::future::Future>::poll::hc72fcaed7ea6645c
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:716:14
- <wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::DeferredWrite<O> as alloc::task::Wake>::wake::he1249cadca69f382
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:554:62
15: 0x5a79 - wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::h235167da4f91e4a1
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:506:10
- <wit_bindgen::rt::async_support::future_support::FutureWriter<T> as core::ops::drop::Drop>::drop::hcaaad8d86644138a
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:379:17
- core::ptr::drop_in_place<wit_bindgen::rt::async_support::future_support::FutureWriter<core::result::Result<core::option::Option<wasi_http_concurrency_guest::wasi::http::types::Fields>,wasi_http_concurrency_guest::wasi::http::types::ErrorCode>>>::h606931453b035b43
at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
- core::mem::drop::hf433209343d7ac34
at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/mem/mod.rs:975:1
- <wasi_http_concurrency_guest::Component as wasi_http_concurrency_guest::exports::wasi::http::handler::Guest>::handle::h74ebd70f1b9d8869
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:249:9
16: 0x2218 - wasi_http_concurrency_guest::exports::wasi::http::handler::_export_handle_cabi::h30c4ecad9fbc835d
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
17: 0x62a2 - wasi:http/handler@0.3.0-rc-2026-03-15#handle
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
Notes
- The
-export: prefix generates correct ABI (fn handle, bare export symbol without [async-lift]). wasmtime 44 finds and calls the export; implicit backpressure via Task.needs_exclusive() works correctly.
- The panic path goes through
FutureWriter::drop → write_and_forget → register_waker, which requires an active task context absent in a sync-lifted call. See #1456 for discussion.
- Related upstream discussion: WebAssembly/WASI #898 (instance reuse opt-out via sync-lift).
Versions
wit-bindgen 0.55.0, wasmtime 44.0.1, wasi:http 0.3.0-rc-2026-03-15
Attempting to write a wasi-http handler with a sync-lifted handler panics in guest code.
How to Reproduce
Using
-export:to sync-lift awasi:http/handler#handleexport:Results in a trap/panic in guest code.
Backtrace
Notes
-export:prefix generates correct ABI (fn handle, bare export symbol without[async-lift]). wasmtime 44 finds and calls the export; implicit backpressure viaTask.needs_exclusive()works correctly.FutureWriter::drop→write_and_forget→register_waker, which requires an active task context absent in a sync-lifted call. See #1456 for discussion.Versions
wit-bindgen 0.55.0, wasmtime 44.0.1, wasi:http 0.3.0-rc-2026-03-15