Description
A Blazor WebAssembly Release AOT build either traps with MONO_WASM: function signature mismatch or hangs while ImageSharp 4.0.0 decodes a PNG into Rgba32.
The strongest indication that this is a Mono WASM AOT generic-instantiation/codegen issue is that merely adding a reachable direct call to PixelOperations<Rgba32>.FromRgba32Bytes makes the previously failing Image.LoadAsync<Rgba32> complete. No PNG data or decoder configuration changes between the failing and working builds.
Library-side tracking with the full diagnosis is SixLabors/ImageSharp#3151.
Reproduction Steps
Clone:
git clone https://github.com/littletoxic/ImageConverterWasm.git
cd ImageConverterWasm
The app uses ImageSharp 4.0.0, which performs build-time license validation. A valid local open-source/commercial license is therefore required to build the v4 dependency. The reporter cannot publish that license. The ImageSharp maintainers can reproduce from SixLabors/ImageSharp#3151.
Publish with WASM AOT enabled:
dotnet publish .\src\ImageConverter\ImageConverter.csproj `
-c Release `
-p:RunAOTCompilation=true `
-p:PublishDir="$env:TEMP\ImageConverterAot\"
dotnet serve --directory "$env:TEMP\ImageConverterAot\wwwroot"
Open the printed URL and upload:
https://github.com/littletoxic/ImageConverterWasm/blob/main/src/ImageConverter/wwwroot/favicon.png
The original app calls:
_image = await Image.LoadAsync(stream);
More focused diagnostic builds established:
// Hangs
using var rgbaImage = await Image.LoadAsync<Rgba32>(stream);
// Completes for the same RGBA PNG
using var rgbImage = await Image.LoadAsync<Rgb24>(stream);
The inverse control also hangs: an RGB PNG that normally completes hangs when explicitly decoded using Image.LoadAsync<Rgba32>.
These calls complete independently:
_ = new Image<Rgba32>(32, 32);
var source = new byte[4];
var destination = new Rgba32[1];
PixelOperations<Rgba32>.Instance.FromRgba32Bytes(
Configuration.Default,
source,
destination,
destination.Length);
Most importantly, keeping the direct FromRgba32Bytes call reachable in the application also makes the formerly hanging Image.LoadAsync<Rgba32> call complete. This changes the AOT generic instance set without changing the decoded input.
Expected behavior
Image.LoadAsync<Rgba32> should decode the 32x32 PNG and return normally in a Release WASM AOT build.
Actual behavior
With the original browser file stream, the runtime traps:
MONO_WASM: function signature mismatch
RuntimeError: function signature mismatch
at dotnet.native.wasm:wasm-function[...]
After buffering the browser stream into a MemoryStream, the focused Image.LoadAsync<Rgba32> diagnostic hangs indefinitely before returning. Depending on which generic calls are reachable, the symptom changes between a signature-mismatch trap and a hang.
Rgb24 and several other pixel/format controls complete normally.
Regression?
ImageSharp 3.1.12 completes the same explicit Image.LoadAsync<Rgba32> test on the same .NET SDK/workload. ImageSharp 4.0.0 does not.
A relevant library code-shape change is:
- ImageSharp 3: the generic pixel loop calls the mutable struct instance method
dp.FromRgba32(sp).
- ImageSharp 4: the loop uses the static abstract interface call
TPixel.FromRgba32(...).
This establishes a library-version regression surface but does not by itself prove which runtime change is responsible.
Known Workarounds
Either:
- Decode into
Rgb24 when dropping alpha is acceptable, or
- Keep a reachable direct call to
PixelOperations<Rgba32>.Instance.FromRgba32Bytes(...) in the application so the required AOT instance appears to be generated.
Disabling RunAOTCompilation also avoids the AOT-specific failure.
Configuration
.NET SDK: 11.0.100-preview.5.26302.115
Runtime: 11.0.0-preview.5.26302.115
WASM workload: 11.0.100-preview.5.26302.115
OS: Windows 10.0.26200 x64
Browser: Microsoft Edge
ImageSharp: 4.0.0
AOT publish succeeds and reports AOT'ing 48 assemblies; the failure occurs only when the browser executes the decode path.
Other information
Related issues:
Attempts to reduce the issue to only a static-abstract-interface generic loop, including a cross-assembly version, completed normally. Therefore the report does not claim that static abstract dispatch alone is sufficient; an additional ImageSharp dispatch/instantiation condition is involved.
This issue was investigated and prepared with assistance from OpenAI Codex.
Description
A Blazor WebAssembly Release AOT build either traps with
MONO_WASM: function signature mismatchor hangs while ImageSharp 4.0.0 decodes a PNG intoRgba32.The strongest indication that this is a Mono WASM AOT generic-instantiation/codegen issue is that merely adding a reachable direct call to
PixelOperations<Rgba32>.FromRgba32Bytesmakes the previously failingImage.LoadAsync<Rgba32>complete. No PNG data or decoder configuration changes between the failing and working builds.Library-side tracking with the full diagnosis is SixLabors/ImageSharp#3151.
Reproduction Steps
Clone:
The app uses ImageSharp 4.0.0, which performs build-time license validation. A valid local open-source/commercial license is therefore required to build the v4 dependency. The reporter cannot publish that license. The ImageSharp maintainers can reproduce from SixLabors/ImageSharp#3151.
Publish with WASM AOT enabled:
Open the printed URL and upload:
https://github.com/littletoxic/ImageConverterWasm/blob/main/src/ImageConverter/wwwroot/favicon.png
The original app calls:
More focused diagnostic builds established:
The inverse control also hangs: an RGB PNG that normally completes hangs when explicitly decoded using
Image.LoadAsync<Rgba32>.These calls complete independently:
Most importantly, keeping the direct
FromRgba32Bytescall reachable in the application also makes the formerly hangingImage.LoadAsync<Rgba32>call complete. This changes the AOT generic instance set without changing the decoded input.Expected behavior
Image.LoadAsync<Rgba32>should decode the 32x32 PNG and return normally in a Release WASM AOT build.Actual behavior
With the original browser file stream, the runtime traps:
After buffering the browser stream into a
MemoryStream, the focusedImage.LoadAsync<Rgba32>diagnostic hangs indefinitely before returning. Depending on which generic calls are reachable, the symptom changes between a signature-mismatch trap and a hang.Rgb24and several other pixel/format controls complete normally.Regression?
ImageSharp 3.1.12 completes the same explicit
Image.LoadAsync<Rgba32>test on the same .NET SDK/workload. ImageSharp 4.0.0 does not.A relevant library code-shape change is:
dp.FromRgba32(sp).TPixel.FromRgba32(...).This establishes a library-version regression surface but does not by itself prove which runtime change is responsible.
Known Workarounds
Either:
Rgb24when dropping alpha is acceptable, orPixelOperations<Rgba32>.Instance.FromRgba32Bytes(...)in the application so the required AOT instance appears to be generated.Disabling
RunAOTCompilationalso avoids the AOT-specific failure.Configuration
AOT publish succeeds and reports
AOT'ing 48 assemblies; the failure occurs only when the browser executes the decode path.Other information
Related issues:
Attempts to reduce the issue to only a static-abstract-interface generic loop, including a cross-assembly version, completed normally. Therefore the report does not claim that static abstract dispatch alone is sufficient; an additional ImageSharp dispatch/instantiation condition is involved.
This issue was investigated and prepared with assistance from OpenAI Codex.