⚠️ Handling Errors
In this example we'll see how to pattern match for the error and output the error message returned from Wasmer.
There will come a time when running a WebAssembly module will not work, and trying to figure out why it does not work can be a difficult task! In the current MVP of WebAssembly, debugging isn't explicitly defined for runtimes both in and out of the browser. So we'll have to write some error handling code ourselves.
In this example, we will load a WebAssembly module that purposely produces an error in its exported function call. The Host (our Rust application) will pattern match for the error and output the error message returned from Wasmer.
First we are going to want to initialize a new project. To do this we can navigate to our project folder, or create one. In this example, we will create a new project. Lets create it and navigate to it:
Rust
Go
PHP
The final Rust code for this example can be found on Github: errors.rs.
Please take a look at the setup steps for Rust.
1
cargo new errors
2
cd errors
Copied!
We have to modify Cargo.toml to add the Wasmer dependencies as shown below:
1
[dependencies]
2
# The Wasmer API
3
wasmer = "2.0"
Copied!
The final Go code for this example can be found on Github: errors.go.
Please take a look at the setup steps for Go.
1
mkdir wasmer-example-errors
2
cd wasmer-example-errors
3
go mod init github.com/$USER/wasmer-example-errors
Copied!
The final PHP code for this example can be found on Github: errors.go.
Please take a look at the setup steps for PHP.
1
mkdir wasmer-example-errors
2
cd wasmer-example-errors
3
composer init --name=wasmer-example-errors
4
composer require wasm/wasm
Copied!
Now that we have everything set up, let's go ahead and try it out!

Handling the error

There is nothing special about the Wasm module, or the way we'll set it up.
The only things we'll need to do are:
    Getting the exported function
    Calling the function;
    Handling the error.
Here is the easy part, getting and calling the function:
Rust
Go
PHP
1
let div_by_zero = instance.exports.get_function("div_by_zero")?.native::<(), i32>()?;
2
let result = div_by_zero.call();
Copied!
1
divByZero, err := instance.Exports.GetFunction("div_by_zero")
2
3
if err != nil {
4
panic(fmt.Sprintln("Failed to get the `div_by_zero` function:", err))
5
}
6
7
_, err = divByZero()
Copied!
1
$divByZero = (new Wasm\Module\Extern($exports[0]))->asFunc();
Copied!
And here is the interesting part, handling the error:
Rust
Go
PHP
1
match result {
2
Ok(_) => {
3
panic!("throw_wasm_error did not error");
4
},
5
Err(e) => {
6
println!("Error caught from `div_by_zero`: {}", e.message());
7
8
let frames = e.trace();
9
let frames_len = frames.len();
10
11
for i in 0..frames_len {
12
println!(
13
" Frame #{}: {:?}::{:?}",
14
frames_len - i,
15
frames[i].module_name(),
16
frames[i].function_name().or(Some("<func>")).unwrap()
17
);
18
}
19
}
20
}
Copied!
1
if err == nil {
2
panic(fmt.Sprintln("`div_by_zero` did not error"))
3
}
4
5
fmt.Println("Error caught from `div_by_zero`:", err)
6
7
trap, ok := err.(*wasmer.TrapError)
8
9
if !ok {
10
panic(fmt.Sprintln("Error was not of the expected type"))
11
}
12
13
frames := trap.Trace()
14
framesLen := len(frames)
15
16
for index, frame := range frames {
17
fmt.Printf(
18
" Frame #%d: function index: %d\n",
19
framesLen - index,
20
frame.FunctionIndex()
21
)
22
}
Copied!
1
try {
2
$result = $divByZero();
3
4
echo '`div_by_zero` did not error'.PHP_EOL;
5
6
exit(1);
7
} catch (Exception $exception) {
8
echo 'Error caught from `div_by_zero`: '.$exception->getMessage().PHP_EOL;
9
}
Copied!
Here we verify the result of calling the function to see if we actually got an error.
If we got an error we format a nice message containing information to help debug the problem:
    The error message.
    The error trace.

Running

We now have everything we need to run the Wasm module, let's do it!
Rust
Go
PHP
Untitled
Untitled
Untitled
You should be able to run it using the cargo run command. The output should look like this:
1
Compiling module...
2
Instantiating module...
3
Calling `div_by_zero` function...
4
Error caught from `div_by_zero`: integer divide by zero
5
Frame #2: "<module>"::"do_div_by_zero_f"
6
Frame #1: "<module>"::"div_by_zero_f"
Copied!
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer.git
2
cd wasmer
3
cargo run --example errors --release --features "cranelift"
Copied!
You should be able to run it using the go run main.go command. The output should look like this:
1
Compiling module...
2
Instantiating module...
3
Calling `div_by_zero` function...
4
Error caught from `div_by_zero`: integer divide by zero
5
Frame #2: function index: 0
6
Frame #1: function index: 50
Copied!
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-go.git
2
cd wasmer-go
3
go test examples/example_errors_test.go
Copied!
You should be able to run it using the php errors.php command.
If you want to run the examples from the Wasmer PHP repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-php.git
2
cd wasmer-php
3
make EXAMPLE=errors test-doc-examples
Copied!
Last modified 4mo ago
Copy link