Now that your fixes have landed @Joel Dice, we should be able to update the example to no longer require the emsdk right?
In theory, yes, although I believe we'll also need to change both wit-bindgen and the dotnet preview build to not try to use EMSDK for wasi builds.
I'm still getting familiar with the dotnet source code, so I'm not sure where those changes need to happen.
we're in the sg for C# right now. I'll aim to get this tracked
@Joel Dice I'm getting an error while running your wasi-http example: https://github.com/dicej/dotnet9-wasi-http-example/tree/main
It's claiming that the component didn't call response-outparam::set but I definitely see it in the app source. Do I need to do an additional step for setting the runtime beyond installing the latest preview (winget install Microsoft.DotNet.SDK.Preview)?
2024-05-21T18:56:04.624831Z ERROR wasmtime_cli::commands::serve: [0] :: Error {
context: "error while executing at wasm backtrace:\n 0: 0x2051f0 - csharp-wasm.wasm!abort\n 1: 0x3b8d8 - csharp-wasm.wasm!RaiseFailFastException\n 2: 0xa59f - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)\n 3: 0xa6cb - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2\n 4: 0x3d239 - csharp-wasm.wasm!RhpReversePInvoke\n 5: 0xcd3c7 - csharp-wasm.wasm!csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle\nnote: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information",
source: UnreachableCodeReached,
}
error: hyper::Error(User(Service), guest never invoked `response-outparam::set` method: error while executing at wasm backtrace:
0: 0x2051f0 - csharp-wasm.wasm!abort
1: 0x3b8d8 - csharp-wasm.wasm!RaiseFailFastException
2: 0xa59f - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)
3: 0xa6cb - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2
4: 0x3d239 - csharp-wasm.wasm!RhpReversePInvoke
5: 0xcd3c7 - csharp-wasm.wasm!csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
Caused by:
wasm trap: wasm `unreachable` instruction executed)
Hmm, that error looks familiar; trying to remember what the solution was.
Thats the first/only message ? The runtime maintains a flag that indicates if it is in cooperative or interruptible state, unmanaged/managed. This error can appear if that flag is out of step, perhaps by an earlier problem
Yeah, I think the "guest never invoked" bit is only a symptom of the real problem
I tried with latest release of wit-bindgen (that should have your fix) and ran directly off our PR as well. Here's the output from wit-bindgen PR that worked for the sample 2 weeks ago. It does have slightly different output but same top-level error:
behay@DESKTOP-MK2J2EE ~\..\dotnet9-wasi-http-example main ≣ +2 ~4 -1 ! wasmtime serve -W max-table-elements=20000 .\target\component.wasm --addr 0.0.0.0:8082
Serving HTTP on http://0.0.0.0:8082/
2024-05-21T19:09:39.631877Z ERROR wasmtime_cli::commands::serve: [0] :: Error {
context: "error while executing at wasm backtrace:\n 0: 0x2051f0 - csharp-wasm.wasm!abort\n 1: 0x3b8d8 - csharp-wasm.wasm!RaiseFailFastException\n 2: 0xa59f - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)\n 3: 0xa6cb - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2\n 4: 0x3d239 - csharp-wasm.wasm!RhpReversePInvoke\n 5: 0xcd3c7 - csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle\n at C:\\Users\\behay\\repos\\dotnet9-wasi-http-example\\ProxyWorld.wit.exports.wasi.http.v0_2_0.IncomingHandlerInterop.cs:18",
source: UnreachableCodeReached,
}
error: hyper::Error(User(Service), guest never invoked `response-outparam::set` method: error while executing at wasm backtrace:
0: 0x2051f0 - csharp-wasm.wasm!abort
1: 0x3b8d8 - csharp-wasm.wasm!RaiseFailFastException
2: 0xa59f - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)
3: 0xa6cb - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2
4: 0x3d239 - csharp-wasm.wasm!RhpReversePInvoke
5: 0xcd3c7 - csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle
at C:\Users\behay\repos\dotnet9-wasi-http-example\ProxyWorld.wit.exports.wasi.http.v0_2_0.IncomingHandlerInterop.cs:18
Caused by:
wasm trap: wasm `unreachable` instruction executed)
can you take a look at ProxyWorld.wit.exports.wasi.http.v0_2_0.IncomingHandlerInterop.cs line 18? Is it right at the beginning of an exported function?
Yes, looking at the generated binding 5: is the invocation of the handler. Above output is with WASMTIME_BACKTRACE_DETAILS=1
I agree it sounds like a panic after the invocation and prior to the set
Now I'm questioning the wisdom of giving my only Windows-capable x86_64 machine to my wife a couple of weeks ago. Gonna have to ask for it back for a bit :)
For reference, this is the generated binding that kicks things off. Looks ok to me:
namespace ProxyWorld.wit.exports.wasi.http.v0_2_0
{
public static class IncomingHandlerInterop {
[UnmanagedCallersOnly(EntryPoint = "wasi:http/incoming-handler@0.2.0#handle")]
public static unsafe void wasmExportHandle(int p0, int p1) {
var resource = new global::ProxyWorld.wit.imports.wasi.http.v0_2_0.ITypes.IncomingRequest(new global::ProxyWorld.wit.imports.wasi.http.v0_2_0.ITypes.IncomingRequest.THandle(p0));
var resource0 = new global::ProxyWorld.wit.imports.wasi.http.v0_2_0.ITypes.ResponseOutparam(new global::ProxyWorld.wit.imports.wasi.http.v0_2_0.ITypes.ResponseOutparam.THandle(p1));
IncomingHandlerImpl.Handle((resource), (resource0));
}
}
}
Which one is line 18? Is that the whole file?
18 is the first var resource =. So it's trapping before calling Handle?
I think the issue is that some runtime init function in the guest isn't being called. I know I ran into this, but I can't remember how I got past it.
I'm running with this in the csproj:
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="9.0.0-*" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="9.0.0-*" />
</ItemGroup>
Which is what is checked in the repo. I could try swapping over to bindgen for mono and the mono runtime, but it sounded like that's not the best path to demo
I got the Windows laptop back; I've got to install dev tools on it, but will try to repro and debug once it's ready.
I'll drop the installs I did since I have them handy
winget install Microsoft.DotNet.SDK.Preview
# install emsdk
Expand-Archive .\main.zip
cd .\emsdk-main\main\emsdk-main
.\emsdk_env.ps1 3.1.60
.\emsdk_env.ps1 activate 3.1.60 --permanent
#install wasi-sdk
#Download and unzip the 22 spot release:
# that path looked odd to me with the +m so I renamed
# I often have a couple wasi-sdk's installed so have a top-level dir for them
https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0.m-mingw64.tar.gz
$env:WASI_SDK_PATH="C:\Users\behay\wasi-sdk\wasi-sdk-22.0"
cargo install wasmtime-cli
cargo install wasm-tools
cargo install wit-bindgen-cli
wasi sdk 22, not sure that one has been tested before. I ran it with 21. Do you need 22 ?
Honestly, I don't remember which version of wasi-sdk I used when I made that demo, but yeah, worth trying 21 instead.
Meanwhile, I'm still waiting for VS to install on my slow internet connection.
If wasi-sdk 21 works, I'll update the README.md to specify that
And then work on getting wasi-sdk 22 working also.
Ok yeah, I'll swap back. I was interested in 22 since it had the fix that would ultimately let us remove the emscripten requirement
We could hypothetically backport that fix to 21 if it's helpful. I'll want to understand why 22 doesn't work in any case.
I'm seeing the same error but going to double check by starting fresh
https://wa2.dev And get the $_initialize function maybe ?
heh if someone has a working wasm, I will definitely diff with it
I got VS and git-bash installed; working on the other deps now
Thats the unstripped wasm that I have
oh hey I get an exception from that component as well. Rolling back wasmtime versions
If you hit a table index error, that's been addressed: https://github.com/bytecodealliance/wasmtime/issues/8504
Mine:
$ wasmtime --version
wasmtime-cli 14.0.4
FWIW, it was definitely working (at least in release mode) on Wasmtime 20.
ah yeah I did bump into the table index error with 20.0.2
Right now I'm building wasmtime from source with the PR that adds max-table-elements support to serve
That _shouldn't_ be necessary for the release build (since the release build doesn't need as big of a table), but I could be misremembering.
I don't see any options for increasing the table in the spin build.sh
Maybe because my wasmtime is old
I don't need them
right; once I changed -c Debug to -c Release it worked with all versions of Wasmtime, new and old
still installing deps on my (wife's) Windows machine; almost there
yeah the component Scott linked is too chonky. Since I'm getting the same error, I'll go ahead and rebuild my own
wasmtime-cli 22.0.0 (8848bac21 2024-05-21) works for me also
dotnet 9.0.100-preview.4.24267.66 doesn't like the project, it seems. It asked me to do dotnet workload update but then barfed with a NullReferenceException when I did that.
Do you mind trying out the component I built?
component.wasm
Other thing I'm testing is if the adapter was potentially mismatched.
I am running with VS Code rather than Visual Code. @Joel Dice which one are you building with?
I installed Visual Studio Community 2022 and the aforementioned dotnet preview and am building using the build.sh in the dotnet9-wasi-http-example repo in git-bash
With your component.wasm:
$ wasmtime serve component.wasm
Serving HTTP on http://0.0.0.0:8080/
2024-05-21T21:41:41.655703Z ERROR wasmtime_cli::commands::serve: [0] :: Error {
context: "error while executing at wasm backtrace:\n 0: 0x204aaa - csharp-wasm.wasm!abort\n 1: 0x3b8de - csharp-wasm.wasm!RaiseFailFastException\n 2: 0xa5a5 - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)\n 3: 0xa6d1 - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2\n 4: 0x3d23f - csharp-wasm.wasm!RhpReversePInvoke\n 5: 0xccf89 - csharp-wasm.wasm!csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle\nnote: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information",
source: UnreachableCodeReached,
}
error: hyper::Error(User(Service), guest never invoked `response-outparam::set` method: error while executing at wasm backtrace:
0: 0x204aaa - csharp-wasm.wasm!abort
1: 0x3b8de - csharp-wasm.wasm!RaiseFailFastException
2: 0xa5a5 - csharp-wasm.wasm!Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*)
3: 0xa6d1 - csharp-wasm.wasm!RhpReversePInvokeAttachOrTrapThread2
4: 0x3d23f - csharp-wasm.wasm!RhpReversePInvoke
5: 0xccf89 - csharp-wasm.wasm!csharp_wasm_ProxyWorld_wit_exports_wasi_http_v0_2_0_IncomingHandlerInterop__wasmExportHandle
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
Caused by:
wasm trap: wasm `unreachable` instruction executed)
nice, at least its reproducible. Now are you able to build a component that works?
Anyone know what this means?
C:\Program Files\dotnet\sdk\9.0.100-preview.4.24267.66\NuGet.targets(741,5): error : Value cannot be null. (Parameter 'path1') [C:\Users\joeld\p\dotnet9-wasi-http-example\App.csproj]
I can't build nothin' at the moment
fwiw I verified that I'm using the proxy adapter for wasmtime 21 while running wasmtime 21
Hmm, your wasm seems ok here. Assuming Im using spin correctly . I renamed yours to stripped.wasm, in target then spin up
I'm calling the commands in build.sh directly. spin in this case is shelling out to build.sh
I'm also passing wasmtime the non-stripped version to get the better error message. Stripped has the same error just without the debug info
wasmtime serve fails for me while spin up works. I am completely misunderstanding what spin up does ?
Interesting; Spin uses wasmtime behind the scenes, but configures it differently. Shouldn't make a difference here, but :shrug:
I'll try with Spin in a minute; currently downgrading to dotnet 9 preview 3 in case that likes me better
Spin is both a dev/build tool and a runtime (e.g. spin build vs. spin up) which can cause confusion.
Sounds like one is calling _initialize and the other isn't
yeah, wow; I can confirm that spin up runs it just fine
or something, I'm rambling now, its late
I _know_ Wasmtime 20 was working at one point; going to try that next
There was a new linker in wasmtime 22 I think I saw
21 won't run it either
interesting, that's we use in CI I think
oh crap, now I finally remember the issue. It wasn't just a table limitation -- the default memory limit for the pooling allocator (which became the default for the serve subcommand in Wasmtime 20) is only 10MB, and the error we've been looking at boils down to an allocation failure.
https://github.com/bytecodealliance/wasmtime/issues/8504#issuecomment-2084255287
The only way I got it working was by rebuilding Wasmtime 20 with a 100MB limit instead of a 10MB one
That's the key, @Bailey Hayes. Kind of embarrassing that it took me longer to debug it this time than it did the first time I debugged it :man_facepalming:
and 22 does not have the fix?
22 hasn't been released. 21 doesn't change the default, I think, but we should be able to override the default via a CLI flag; looking for that now.
Honestly same day delivery (debugging and getting an answer) is a pretty fantastic experience. Thank you for jumping on this
wasmtime serve -O pooling-allocator=n component.wasm works
not sure yet how to leave the pooling allocator enabled but give it a higher limit
doesn't look like there's a CLI option yet for https://docs.rs/wasmtime/latest/wasmtime/struct.PoolingAllocationConfig.html#method.memory_pages, unfortunately, so disabling the pooling allocator entirely is the only option for now
should be fine for demo purposes
IT WORKS!!!
I just managed to build and run everything on Ubuntu 24.04 (arm64), so we're no longer tied to Windows. I'll work with @Scott Waye to get stuff upstreamed.
Note that only the Release build works on Linux at the moment. The Debug build triggers an assertion failure in free which Scott is working to address.
I also removed the EMSDK dependency, BTW.
Code is available at https://github.com/dicej/dotnet9-wasi-http-example/tree/linux and https://github.com/dicej/runtimelab/tree/linux-nativeaot-llvm
Would it make sense to start publishing WASI-SDK as a NuGet package so users can just add a package reference to their project instead of installing it separately?
Ditto for wit-bindgen and wasm-tools? I'm thinking of how to minimize friction for targeting WASI using .NET.
that would help, and is the intent of the repo we've got staged at https://github.com/bytecodealliance/componentize-dotnet. We are planning on taking the prototype in https://github.com/SteveSandersonMS/wasm-component-sdk which wraps all that up and makes it as simple as adding the reference. I'm currently waiting on Steve to add a license so we can move it and fix it up
I worked with steve and got a license added, I've moved the code over and started to fill out the BCA requirements: https://github.com/bytecodealliance/componentize-dotnet/pull/1, Next week I will start to fix the project up so that it builds
the Linux and WASI-SDK 22 and no-more-EMSDK PR has been merged: https://github.com/dotnet/runtimelab/pull/2592
@James Sturtevant let me know if I can help update componentize-dotnet and anything else needed to get us to where we can publish NuGet packages.
Some of the folks here are already part of the GH team dotnet-core and part of the bytecodealliance nuget org.
I have not set the repo secret for the publish token. Dotnet-core maintainers should be able to do this too. Let me know if I can help
quick update, I've got things updated and working on a final e2e test where the packages aren't updating properly.
Do you know when those compiler changes will get released? Will pick them up and remove emsdk as a seperate change once ready. We will also probably want to remove these lines from wit-bingen: https://github.com/bytecodealliance/wit-bindgen/blob/2645c4f7ddefa0844a91b214267b1674e45d4884/crates/csharp/src/csproj.rs#L114-L119. We will still need to compile that file, What should be used?
James Sturtevant said:
Do you know when those compiler changes will get released?
Good question. I don't know who or what (e.g. CI) publishes NuGet package releases for NativeAOT-LLVM. Maybe @Scott Waye knows?
We will also probably want to remove these lines from wit-bingen: https://github.com/bytecodealliance/wit-bindgen/blob/2645c4f7ddefa0844a91b214267b1674e45d4884/crates/csharp/src/csproj.rs#L114-L119. We will still need to compile that file, What should be used?
$WASI_SDK_PATH/bin/clang should work, e.g. https://github.com/WebAssembly/wasi-sdk?tab=readme-ov-file#use
I think they are already publsihed. When the PR is merged a CI publish job is triggerred
The date can be checked from https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-experimental
Perfect; I'm about to test that out as part of my upcoming wit-bindgen PR, which I'm developing and testing on Linux.
UK date format but is the 4th June
Oh, but CI is probably not publishing Linux packages yet, right?
Hmm, good question
And I'm on Linux/ARM64 to make it doubly obscure :)
I guess we first need to get Linux/ARM64 in the pipeline for the PRs, we might be able to get away without running the tests in the short term
The other hurdle is that WASI-SDK doesn't publish Linux/ARM64 artifacts yet; I can make a PR to address that, though.
Right, that will obviously be needed first.
it would be musl libc I suppose ?
Good question; I'm on Ubuntu-Asahi, so I was assuming glibc, but musl might be more portable.
I think the runtime repo has configs for both so we can try glibc
@Scott Waye is there linux amd64? I should be able to test this win the componentize-dotnet repo I think
Yeah, we should definitely start with that and move on to ARM once WASI-SDK artifacts are available.
We will have to get x64 set up, I will create a PR to see what happens
sounds good let me know and can give it a try
@Joel Dice I don't have it published to nuget but I merged changes that should work. You can download the latest package from https://github.com/bytecodealliance/componentize-dotnet/actions/runs/9406419877
So just looked and I do have access to GH team dotnet-core but not nuget. could some one with access to that help set the repo secret for the publish token?
Not sure what to look for , "Deploy Keys" ?
sorry, didn't mean to tag you specifically, there are no secrets in the repo and I can't get any since I don't have access to BCA nuget
What's the plan for referencing the *ILCompiler.LLVM package in a project in a platform-agnostic way? For example, I currently have a reference to runtime.linux-arm64.Microsoft.DotNet.ILCompiler.LLVM in my project, but that obviously only makes sense on Linux/ARM64. Or will that just be taken care of behind the scenes when we start using the componentize-dotnet package?
I believe componentize-dotnet should handle this but looks like we have it hard coded right now. Opened https://github.com/bytecodealliance/componentize-dotnet/issues/13 to track
both wit-bindgen and componentize-dotnet no longer use the emsdk! https://github.com/bytecodealliance/wit-bindgen/pull/969 and https://github.com/bytecodealliance/componentize-dotnet/pull/14
Last updated: Dec 13 2025 at 20:04 UTC