Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Error Handling

Traps

A Trap represents a runtime error in WebAssembly execution.

TrapCode

pub const TrapCode = enum {
    Unreachable,
    IntegerDivisionByZero,
    IntegerOverflow,
    IndirectCallToNull,
    UndefinedElement,
    UninitializedElement,
    OutOfBoundsMemoryAccess,
    OutOfBoundsTableAccess,
    IndirectCallTypeMismatch,
    StackOverflow,
    OutOfMemory,
    // ... more codes
};

ExecResult

Function calls return an ExecResult:

const result = try instance.call("func", &args);

switch (result) {
    .ok => |val| {
        // Success - val may be null for void functions
        if (val) |v| {
            std.debug.print("Result: {d}\n", .{v.readAs(i32)});
        }
    },
    .trap => |trap| {
        // Trap occurred
        std.debug.print("Trap: {s}\n", .{@tagName(trap.code)});
        
        // Get detailed message
        const msg = try trap.allocPrint(allocator);
        defer allocator.free(msg);
        std.debug.print("Details: {s}\n", .{msg});
    },
}

Trap Message

Get a human-readable trap message:

if (result.trap) |trap| {
    const msg = try trap.allocPrint(allocator);
    defer allocator.free(msg);
    std.debug.print("Trap: {s}\n", .{msg});
}

Host Errors

Host functions can return errors:

fn host_divide(
    _: ?*anyopaque,
    _: *wasmz.HostContext,
    params: []const wasmz.RawVal,
    results: []wasmz.RawVal,
) wasmz.HostError!void {
    const a = params[0].readAs(i32);
    const b = params[1].readAs(i32);
    
    if (b == 0) {
        return wasmz.HostError.Trap;
    }
    
    results[0] = wasmz.RawVal.from(@divTrunc(a, b));
}

Common Errors

Module Compilation

var module = wasmz.Module.compile(engine, bytes) catch |err| {
    switch (err) {
        error.InvalidWasm => {
            std.debug.print("Invalid WASM binary\n", .{});
        },
        error.UnsupportedFeature => {
            std.debug.print("Feature not supported\n", .{});
        },
        error.OutOfMemory => {
            std.debug.print("Out of memory\n", .{});
        },
        else => return err,
    }
    return;
};

Instantiation

var instance = wasmz.Instance.init(&store, module, linker) catch |err| {
    switch (err) {
        error.ImportNotSatisfied => {
            std.debug.print("Missing imports:\n", .{});
            for (module.imported_funcs) |imp| {
                if (linker.get(imp.module_name, imp.func_name) == null) {
                    std.debug.print("  {s}::{s}\n", .{ imp.module_name, imp.func_name });
                }
            }
        },
        error.ImportSignatureMismatch => {
            std.debug.print("Import signature mismatch\n", .{});
        },
        else => return err,
    }
    return;
};

Memory Limit

When memory limit is exceeded:

var engine = try wasmz.Engine.init(allocator, .{
    .mem_limit_bytes = 64 * 1024 * 1024, // 64 MB
});

// If WASM tries to grow memory beyond limit:
// result.trap.code == .OutOfMemory

Stack Overflow

When call stack is exhausted:

// Recursive function without base case
// result.trap.code == .StackOverflow