Stream: WASI-Virt

Topic: Updating to WASI v0.2.9 (or p3)?


view this post on Zulip zslayton (Jun 11 2026 at 11:36):

Hi! I'm trying to use WASI-Virt's programmatic API to wrap a component. This project seemed to work a few months ago, so I suspect I updated something in my toolchain that caused it to break.

When I run this code:

let mut virtualizer = wasi_virt::WasiVirt::new();
virtualizer.allow_all();
virtualizer.fs().deny_host_preopens();

// ...add some `FsEntry`s...

virtualizer.compose_component_path(&tmp_original_component);
let component_bytes = virtualizer.finish().unwrap();

...I get this error:

Unable to compose virtualized adapter into component.
Make sure virtualizations are enabled and being used.

Caused by:
no dependencies of component `/tmp/.tmpeIaGdX` were found

Some web searches have led me to suspect that this is being caused by --target wasm32-wasip2 on recent compiler versions emitting imports for WASI 0.2.9 while wasi-virt expects 0.2.3. I've tried adding:

        virtualizer.wasi_version(semver::Version::new(0, 2, 9));

but that only causes the library to complain that 0.2.9 is not supported.

Some questions:

Thanks!

view this post on Zulip Bailey Hayes (Jun 11 2026 at 13:41):

Ideally we add semver linking to wasi-virt to maintain forward compatibility. One quick workaround:
https://github.com/bytecodealliance/WASI-Virt/issues/110#issuecomment-2754104297

view this post on Zulip zslayton (Jun 11 2026 at 14:50):

That helped! Now I have an exciting new error :sweat_smile:.

thread 'tokio-rt-worker' (416601) panicked at src/main.rs:764:10:
instantiating WASI module: component imports instance `wasi:http/types@0.2.3`,
    but a matching implementation was not found in the linker

Caused by:
    0: instance export `fields` has the wrong type
    1: resource implementation is missing

I'm afraid I don't know enough about the differences between 0.2.3 and 0.2.9 to speculate why the sed command wasn't sufficient here.

view this post on Zulip zslayton (Jun 18 2026 at 10:05):

I've been doing some tinkering to try and update WASI-Virt to a newer version of WASI. Before I invest more time into it, I wanted to ask for some guidance.

WASI 0.3 is out now ( :tada: ), but I understand it will be a couple of months before there's a widely available wasm32-wasip3 target available in cargo. For the moment, I could try to update WASI-Virt to v2.12 (the latest 2.x release), which in theory would work with any component targeting 2.x. Is that true in practice? Not too long ago, many tools were doing exact version-matching rather than SemVer-compatible matching. Rust's wasm32-wasip2 target currently depends on WASI 0.2.9, so if it did an exact match then upgrading WASI-Virt to 0.2.12 wouldn't be very useful.

Currently WASI-Virt maintains separate code paths for WASI 0.2.1 and 0.2.3. I expect this decision is tied to the exact-version-matching I described. When WASI 0.2.12 @unstable features are enabled in wit-bindgen::generate!, it produces code that's not directly compatible with 0.2.1 or 0.2.3. If we had 0.2.12 support and semver linking, could we maintain a single version?

Ideally we add semver linking to wasi-virt to maintain forward compatibility.

Could you describe what would be needed here? Where would this logic need to live?

view this post on Zulip Bailey Hayes (Jun 18 2026 at 14:05):

It'd be great to get a release out of WASI-Virt with 0.2 before anyone takes on 0.3

view this post on Zulip Bailey Hayes (Jun 18 2026 at 14:07):

A canonical interface version allows both backwwards and forwads compatibility (with limitations): https://github.com/WebAssembly/component-model/blob/5452862053a7114064ae6d7e4c90488b3c2a7b45/design/mvp/Explainer.md?plain=1#L2921

view this post on Zulip Bailey Hayes (Jun 18 2026 at 14:17):

In wit-parser, Resolve::merge_world_imports_based_on_semver does the world-trimming: it deduplicates imports based on their semver versions, always selecting the maximum version, and only deduplicates interfaces that are semver-compatible. For example: wasi:cli/environment@0.2.0 + @0.2.1 collapse to @0.2.1, but @0.2.0 + @0.3.0 stay distinct. It's enabled by default in wit-component's encode path and toggleable via flags. This is what I would use for this. Also rather than using the wasm-compose crate, I'd move to wac.

view this post on Zulip zslayton (Jul 03 2026 at 14:50):

I've taken a crack at this, but I'm afraid I've hit a wall. My code is here.

I've updated various dependencies to modern versions and am now using wac for composition. cargo test fails on fs-virt-dir-read:

Error: Error creating virtual adapter "tests/cases/fs-virt-dir-read.toml" for "target/wasm32-wasip1/release/file_read.wasm"

Caused by:
    0: failed to merge with fs world
    1: failed to add export `wasi:filesystem/preopens@0.2.3`
    2: failed validating export of `wasi:filesystem/preopens@0.2.3`
    3: failed validating transitive import dep `wasi:filesystem/types@0.2.3`
    4: world exports `wasi:io/streams@0.2.3` but it's also transitively used by an import which means that this is not valid
test virt_test ... FAILED

As the failure occurs during the call to merge_worlds with fs_world+base_world, I added some debug printing to the finish() method to check on the state of the imports/exports at a couple of different points:

> "tests/cases/fs-virt-dir-read.toml"
-- after IO merge --
world virtual-base {
  import wasi:cli/exit@0.2.3; // Id { idx: 30 }
  import wasi:io/error@0.2.3; // Id { idx: 1 }
  import wasi:io/poll@0.2.3; // Id { idx: 2 }
  import wasi:io/streams@0.2.3; // Id { idx: 3 }
  export wasi:cli/exit@0.2.3; // Id { idx: 30 }
  export wasi:io/error@0.2.3; // Id { idx: 1 }
  export wasi:io/poll@0.2.3; // Id { idx: 2 }
  export wasi:io/streams@0.2.3; // Id { idx: 3 }
}
-- just before fs merge --
world virtual-base {
  import wasi:cli/exit@0.2.3; // Id { idx: 30 }
  import wasi:io/error@0.2.3; // Id { idx: 1 }
  import wasi:io/poll@0.2.3; // Id { idx: 2 }
  import wasi:io/streams@0.2.3; // Id { idx: 3 }
  import wasi:cli/stdin@0.2.3; // Id { idx: 7 }
  import wasi:cli/stdout@0.2.3; // Id { idx: 8 }
  import wasi:cli/stderr@0.2.3; // Id { idx: 9 }
  import wasi:cli/terminal-input@0.2.3; // Id { idx: 10 }
  import wasi:cli/terminal-output@0.2.3; // Id { idx: 11 }
  import wasi:cli/terminal-stdin@0.2.3; // Id { idx: 12 }
  import wasi:cli/terminal-stdout@0.2.3; // Id { idx: 13 }
  import wasi:cli/terminal-stderr@0.2.3; // Id { idx: 14 }
  export wasi:cli/exit@0.2.3; // Id { idx: 30 }
  export wasi:io/error@0.2.3; // Id { idx: 1 }
  export wasi:io/poll@0.2.3; // Id { idx: 2 }
  export wasi:io/streams@0.2.3; // Id { idx: 3 }
  export wasi:cli/stdin@0.2.3; // Id { idx: 7 }
  export wasi:cli/stdout@0.2.3; // Id { idx: 8 }
  export wasi:cli/stderr@0.2.3; // Id { idx: 9 }
  export wasi:cli/terminal-input@0.2.3; // Id { idx: 10 }
  export wasi:cli/terminal-output@0.2.3; // Id { idx: 11 }
  export wasi:cli/terminal-stdin@0.2.3; // Id { idx: 12 }
  export wasi:cli/terminal-stdout@0.2.3; // Id { idx: 13 }
  export wasi:cli/terminal-stderr@0.2.3; // Id { idx: 14 }
}

Having found this issue, I also checked for version skew. However, I have confirmed that my virtual adapters, my wasm-tools binary, and WASI-Virt are all being built using the same version of wac, wit-component, etc.

If anyone has any pointers, I'd appreciate it.

view this post on Zulip zslayton (Jul 03 2026 at 14:51):

I've taken a crack at this, but I'm afraid I've hit a wall. My code is here.

I've updated various dependencies to modern versions and am now using wac for composition. cargo test fails on fs-virt-dir-read:

Error: Error creating virtual adapter "tests/cases/fs-virt-dir-read.toml" for "target/wasm32-wasip1/release/file_read.wasm"

Caused by:
    0: failed to merge with fs world
    1: failed to add export `wasi:filesystem/preopens@0.2.3`
    2: failed validating export of `wasi:filesystem/preopens@0.2.3`
    3: failed validating transitive import dep `wasi:filesystem/types@0.2.3`
    4: world exports `wasi:io/streams@0.2.3` but it's also transitively used by an import which means that this is not valid
test virt_test ... FAILED

As the failure occurs during the call to merge_worlds with fs_world+base_world, I added some debug printing to the finish() method to check on the state of the imports/exports at a couple of different points:

> "tests/cases/fs-virt-dir-read.toml"
-- after IO merge --
world virtual-base {
  import wasi:cli/exit@0.2.3; // Id { idx: 30 }
  import wasi:io/error@0.2.3; // Id { idx: 1 }
  import wasi:io/poll@0.2.3; // Id { idx: 2 }
  import wasi:io/streams@0.2.3; // Id { idx: 3 }
  export wasi:cli/exit@0.2.3; // Id { idx: 30 }
  export wasi:io/error@0.2.3; // Id { idx: 1 }
  export wasi:io/poll@0.2.3; // Id { idx: 2 }
  export wasi:io/streams@0.2.3; // Id { idx: 3 }
}
-- just before fs merge --
world virtual-base {
  import wasi:cli/exit@0.2.3; // Id { idx: 30 }
  import wasi:io/error@0.2.3; // Id { idx: 1 }
  import wasi:io/poll@0.2.3; // Id { idx: 2 }
  import wasi:io/streams@0.2.3; // Id { idx: 3 }
  import wasi:cli/stdin@0.2.3; // Id { idx: 7 }
  import wasi:cli/stdout@0.2.3; // Id { idx: 8 }
  import wasi:cli/stderr@0.2.3; // Id { idx: 9 }
  import wasi:cli/terminal-input@0.2.3; // Id { idx: 10 }
  import wasi:cli/terminal-output@0.2.3; // Id { idx: 11 }
  import wasi:cli/terminal-stdin@0.2.3; // Id { idx: 12 }
  import wasi:cli/terminal-stdout@0.2.3; // Id { idx: 13 }
  import wasi:cli/terminal-stderr@0.2.3; // Id { idx: 14 }
  export wasi:cli/exit@0.2.3; // Id { idx: 30 }
  export wasi:io/error@0.2.3; // Id { idx: 1 }
  export wasi:io/poll@0.2.3; // Id { idx: 2 }
  export wasi:io/streams@0.2.3; // Id { idx: 3 }
  export wasi:cli/stdin@0.2.3; // Id { idx: 7 }
  export wasi:cli/stdout@0.2.3; // Id { idx: 8 }
  export wasi:cli/stderr@0.2.3; // Id { idx: 9 }
  export wasi:cli/terminal-input@0.2.3; // Id { idx: 10 }
  export wasi:cli/terminal-output@0.2.3; // Id { idx: 11 }
  export wasi:cli/terminal-stdin@0.2.3; // Id { idx: 12 }
  export wasi:cli/terminal-stdout@0.2.3; // Id { idx: 13 }
  export wasi:cli/terminal-stderr@0.2.3; // Id { idx: 14 }
}

Having found this issue, I also checked for version skew. However, I have confirmed that my virtual adapters, my wasm-tools binary, and WASI-Virt are all being built using the same version of wac, wit-component, etc.

Note that at this point, I'm only trying to change the way resolution works. Once I get it working, I'll upgrade the adapter from WASI 0.2.3 to WASI 0.2.12.

If anyone has any pointers, I'd appreciate it.

view this post on Zulip zslayton (Jul 07 2026 at 08:46):

Following up on this: I created a PR with my changes. Victor told me that the issue I've encountered is a known blocker that makes achieving this in p2 more or less impossible. The best path forward is to migrate WASI-Virt to p3. I'm now looking into how the availability of async would allow us to sidestep component-model#208 as that's not obvious to me yet.


Last updated: Jul 29 2026 at 05:03 UTC