Wasmtime Version Migration Guide
This tutorial’s code targets wasmtime 29 and wit-bindgen 0.41. If you’re using a newer version, the concepts (WIT files, generated bindings, resources, composition) are the same — but some Rust APIs have changed. This guide covers the significant migrations.
The largest API changes happened at wasmtime 30 (WasiView split), wasmtime 36 (WasiCtxView return type), and wasmtime 40 (sync/async separation for component imports). Versions beyond v40 have been more incremental for the Component Model APIs — the bindgen! macro, Component::new(), Linker, Engine, and Store APIs have remained largely stable. Wasmtime 44 added experimental map<K, V> support. Wasmtime 45 added Component reflection APIs and a copying GC collector, and raised the minimum Rust version to 1.93.0. As of May 2026, the latest release is wasmtime 45.
Wasmtime 30: WasiView Split
wasmtime 30 split the WasiView trait into two separate traits: IoView and WasiView.
Before (wasmtime 29):
#![allow(unused)]
fn main() {
impl WasiView for State {
fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi }
fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
}
After (wasmtime 30+):
#![allow(unused)]
fn main() {
impl IoView for State {
fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
impl WasiView for State {
fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi }
}
}
Both traits must be implemented. IoView provides the resource table; WasiView provides the WASI context.
Wasmtime 36: WasiCtxView and p2 Linker
wasmtime 36 changed WasiView::ctx() to return WasiCtxView<'_> instead of &mut WasiCtx, removed WasiView::table(), and moved add_to_linker_sync to wasmtime_wasi::p2::add_to_linker_sync.
Before (wasmtime 29–35):
#![allow(unused)]
fn main() {
impl WasiView for State {
fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi }
fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
wasmtime_wasi::add_to_linker_sync(&mut linker)?;
}
After (wasmtime 36+):
#![allow(unused)]
fn main() {
impl WasiView for State {
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView { ctx: &mut self.wasi, table: &mut self.table }
}
}
wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
}
The WasiCtxView struct bundles both the WASI context and the resource table into a single return value. The exact field layout is not a stable public API — check the wasmtime docs for the current construction pattern if the above doesn’t compile.
Wasmtime 39: Component Model Async Enabled by Default
wasmtime 39 enabled the component-model-async feature by default, making [Typed]Func::call_async available without a feature flag. On wasmtime 36–38, the feature existed but was off by default and required enabling the component-model-async Cargo feature.
Async support is still evolving. The Component Model spec defines streams and futures, and wasmtime is implementing them incrementally — but the APIs may change between releases. If you’re building async plugin systems on wasmtime 39+, check the Component Model spec and the wasmtime repo for the current status.
This doesn’t affect the tutorial’s synchronous examples.
Wasmtime 40: Sync Component Imports Removed
wasmtime 40 removed the ability to implement component imports with async host functions and call them synchronously from guest code. In wasmtime 29–39, you could write async host-side implementations and the runtime would bridge them for synchronous guest calls. In v40+, the sync and async worlds are strictly separated: if the host uses async, the guest must also use async.
This matters if you’re using the Component Model for host→guest calls. If your project has async host functions implementing component imports (e.g., an async get_config that the guest calls), you have two options on wasmtime 40+:
- Make the guest async too. Enable the
component-model-asyncCargo feature (on by default in v39+), addasyncto the guest function signatures, and call throughcall_asyncinstead ofcall. - Keep the host synchronous. If your host function doesn’t actually need async, implement it as a plain sync function — no
asynckeyword — and the guest can call it synchronously as before.
The tutorial’s examples are fully synchronous (host and guest), so this change doesn’t affect them. If you’re extending the examples with async host operations — say, a plugin that fetches data from a network resource — you’ll need to go all-in on async on wasmtime 40+.
Before (wasmtime 29–39):
#![allow(unused)]
fn main() {
// Host: async implementation
async fn host_fetch(&mut self, url: String) -> String {
reqwest::get(&url).await.text().await.unwrap()
}
// Guest: synchronous call — the runtime bridges automatically
let data = host_fetch("https://example.com");
}
After (wasmtime 40+):
#![allow(unused)]
fn main() {
// Host: async implementation (same)
async fn host_fetch(&mut self, url: String) -> String {
reqwest::get(&url).await.text().await.unwrap()
}
// Guest: must also be async — call through call_async, not call
let data = bindings.call_host_fetch_async(&mut store, "https://example.com").await?;
// The guest function signature gets the `async` keyword, and the host
// must use call_async instead of call. You can't mix sync and async.
}
Wasmtime 44: Experimental map<K, V> Support
wasmtime 44 added experimental support for the map<K, V> type in the Component Model. If your WIT files use map<string, u32> or similar map types, wasmtime 44+ can compile and instantiate them. Earlier versions will reject WIT files that use map.
This doesn’t affect the tutorial’s code — none of the examples use map types — but if you’re extending the examples with key-value interfaces, map in WIT is now an option on wasmtime 44+. On earlier versions (including the wasmtime 29 this tutorial targets), the WIT parser will reject map as an unknown type with an error like unknown type 'map' in WIT file.
Wasmtime 45: Component Reflection, Copying GC, Rust 1.93
wasmtime 45 (released 2026-05-21) added Component reflection APIs (inspect the compiled in-memory view of component instructions, similar to what Module already offered) and an initial copying garbage collector. It also raised the minimum Rust version to 1.93.0.
The tutorial code itself doesn’t need changes, but you’ll need Rust 1.93.0 or later to compile wasmtime 45. If you’re on an older toolchain, run rustup update before upgrading. The synchronous Component Model APIs (bindgen!, Linker, Component::new, Store) are unchanged — the reflection and GC additions are opt-in features.
One forward-looking note: wasmtime 45’s CLI warns that wasi-common and wasi-threads are slated for removal in wasmtime 47. If you’re using those crates directly (the tutorial uses wasmtime-wasi, not wasi-common), plan to migrate before upgrading to 47.
wit-bindgen Version Changes
The generated trait and type names have changed across wit-bindgen versions. If you’re using a version beyond 0.41 and the generated code doesn’t match the tutorial, check the wit-bindgen docs for the current trait signatures — the patterns are the same, but names may differ.
The tutorial targets wit-bindgen 0.41. As of May 2026, the latest release is wit-bindgen 0.57. The version gap is significant: 0.42+ reorganized the generated module structure (trait names, import paths, and the Guest vs GuestTraits split changed). The wit_bindgen::generate! macro still works the same way, and the export! macro still registers your implementation — but the exact trait you implement and the import path to reach it may differ. If you’re on wit-bindgen 0.50+, check the wit-bindgen changelog for migration steps.
WasiP1Ctx: A Simpler Alternative
Parts 1–5 of this tutorial use WasiCtx + ResourceTable + WasiView as separate fields. Part 6 and Part 7 use WasiP1Ctx — a convenience type from wasmtime_wasi::preview1 that bundles both into a single field:
#![allow(unused)]
fn main() {
use wasmtime_wasi::preview1::WasiP1Ctx;
struct HostState {
wasi: WasiP1Ctx,
}
wasmtime_wasi::preview1::add_to_linker_sync(&mut linker, |state: &mut HostState| &mut state.wasi)?;
}
Use WasiP1Ctx when you don’t need separate access to the resource table (most hosts don’t). Use WasiCtx + ResourceTable when you need to pass the resource table to other wasmtime APIs directly. Both approaches work identically from the plugin’s perspective.