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
- 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.
- Catch ShenyuWasmException around the plugin's invoke call and map it to an appropriate gateway error response for clients.
- Validate inputs to the wasm function before invoking to avoid the module's error/abort path.
- 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
- Fix wasm code to return error codes via memory instead of calling proc_exit on failure paths.
- Validate inputs before invoking wasm functions.
- Compile wasm with panic handlers (e.g. Rust panic=unwind with catch_unwind) rather than abort->proc_exit.
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
- Clock moved backwards. Refusing to generate id for
- we not support metric registration for type
- Can't find wasm file
- memory not available in wasm file
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)