apache/shenyu · error · ShenyuWasmException

WASI proc_exit( ) from

Error message

WASI proc_exit(${exitCode}) from ${wasmName}

What it means

WasmLoader registers a WASI proc_exit host stub; when the wasm module calls proc_exit with a non-zero exit code — the module's equivalent of exiting with failure — the stub throws ShenyuWasmException carrying the exit code and module name. This surfaces a deliberate abort inside the wasm program rather than a gateway fault, and only for exitCode == 0 is the call treated as success.

Solutions

  1. Inspect the wasm module's logic (or its source) for the code path calling proc_exit/exit and fix the underlying condition that triggers the non-zero exit.
  2. Catch ShenyuWasmException around the plugin's invoke call and map it to an appropriate gateway error response for clients.
  3. Validate inputs to the wasm function before invoking to avoid the module's error/abort path.
  4. Rebuild the module with panic handlers that return error codes through memory instead of calling proc_exit.

Example fix

// before (wasm side)
if (bad_input) { proc_exit(1); }
// after
if (bad_input) { set_err_code(ERR_BAD_INPUT); return; }
Defensive patterns

Strategy: try-catch

Try / catch

try {
    Object result = wasmLoader.invoke(...);
} catch (ShenyuWasmException e) {
    if (e.getMessage().startsWith("WASI proc_exit(")) {
        // map module abort to gateway error response
        return WebFluxResultUtils.failedResult(...);
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing an exported wasm function that internally calls wasi_snapshot_preview1.proc_exit with a non-zero argument, e.g. after hitting an unrecoverable condition (assertion failure, missing WASI resource, aborted computation) inside the module.

Common situations: wasm modules compiled with WASI support aborting on panics (Rust panic=abort calls proc_exit(1)); modules calling exit() on error paths; wasm code failing on unexpected input and terminating itself.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/925d3720672c837c. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-plugin/shenyu-plugin-wasm-api/src/main/java/org/apache/shenyu/plugin/wasm/api/loader/WasmLoader.java:181

        var options = com.dylibso.chicory.wasi.WasiOptions.builder()
                .withStdout(System.out)
                .withStderr(System.err)
                .build();
        var wasi = com.dylibso.chicory.wasi.WasiPreview1.builder()
                .withOptions(options)
                .build();
        store.addFunction(wasi.toHostFunctions());

        // Override proc_exit with a no-op: valid WASI program exit (proc_exit(0))
        // is normal termination and should not propagate as a Java exception in
        // a hosted plugin runtime.
        store.addFunction(new HostFunction(
                "wasi_snapshot_preview1", "proc_exit",
                FunctionType.of(List.of(ValType.I32), List.of()),
                (inst, args) -> {
                    int exitCode = (int) args[0];
                    if (exitCode != 0) {
                        throw new ShenyuWasmException("WASI proc_exit(" + exitCode + ") from " + wasmName);
                    }
                    return new long[0];
                }
        ));
    }

    private void registerBuiltinHostFunctions(final Store store) {
        store.addFunction(new HostFunction(
                IMPORT_WASM_MODULE_NAME, "get_args",
                FunctionType.of(List.of(ValType.I64, ValType.I64, ValType.I32), List.of(ValType.I32)),
                (instance, args) -> new long[]{onGetArgs(args[0], args[1], (int) args[2])}
        ));
        store.addFunction(new HostFunction(
                IMPORT_WASM_MODULE_NAME, "put_result",
                FunctionType.of(List.of(ValType.I64, ValType.I64, ValType.I32), List.of(ValType.I32)),
                (instance, args) -> new long[]{onPutResult(args[0], args[1], (int) args[2])}
        ));
    }

View on GitHub (pinned to 567142e072)