Skip to content

Commit dcb8db3

Browse files
committed
changelog for workers-rs panic recovery
1 parent 824f50f commit dcb8db3

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: Panic Recovery for Rust Workers
3+
description: Making workers-rs deployments more reliable with panic recovery
4+
date: 2025-09-19
5+
---
6+
7+
import { WranglerConfig, Aside } from "~/components";
8+
9+
A long-standing problem we've had with [workers-rs](https://github.com/cloudflare/workers-rs) is that its Rust panics are non-recoverable, and can put the worker into an invalid state.
10+
11+
Working on the [wasm-bindgen](https://github.com/wasm-bindgen/wasm-bindgen) internals, we've been able to implement a solution for panic recovery to ensure more reliable deployments.
12+
13+
## Fixing Rust Panics with Wasm Bindgen
14+
15+
We use [wasm-bindgen](https://github.com/wasm-bindgen/wasm-bindgen) to build and deploy Rust workers, but Wasm Bindgen is not designed to support recoverable panics.
16+
17+
When a panic happens in Wasm Bindgen, the entire Wasm application is considered to be in an invalid state, and any further function calls could result in overflows or memory exceptions.
18+
19+
But Wasm is a virtual machine - if we can reset all the Wasm internal state back to its initial state then we can continue to take new requests.
20+
21+
It's possible to add a panic handler in Rust to detect immediately when a panic happens:
22+
23+
```rust
24+
std::panic::set_hook(Box::new(move |panic_info| {
25+
hook_impl(panic_info);
26+
}));
27+
```
28+
29+
With some extra wiring we can then export a registration function to JavaScript to allow a custom panic hook to be attached:
30+
31+
```js
32+
import { setPanicHook } from "./index.js";
33+
setPanicHook(function (err) {
34+
console.error("Panic handler!", err);
35+
});
36+
```
37+
38+
We then call a new reset state function when a panic occurs, to reinitialize the Wasm application to back to as it was when the application first started.
39+
40+
## Resetting VM State in Wasm Bindgen
41+
42+
We worked upstream on the Wasm Bindgen project to implement a new [`--experimental-reset-state-function` compilation option](https://github.com/wasm-bindgen/wasm-bindgen/pull/4644) which outputs a new `__wbg_reset_state` function.
43+
44+
This function clears all internal state related to the Wasm VM, and also ensures object references are uniquely associated with the Wasm instance identity. Wasm bindgen exports stateless JS wrapper functions which call into Wasm. Updating their internal
45+
Wasm instance binding to the new instance allows exposing the new Wasm instance without having to rebind the exported functions.
46+
47+
One other necessary change here was associating Wasm-created JS objects with an instance identity. If a JS object created by an earlier instance is then passed into a new instance later on, a new "stale object" error is specially thrown when using this feature.
48+
49+
## Layered Solution
50+
51+
By implementing only the minimal primitive upstream in Wasm Bindgen necessary, we could then comprehensively solve the remaining JS state concerns for workers-rs specifically.
52+
53+
For this a proxy wrapper was needed to ensure all top-level exported class instantiations (such as for Rust Durable Objects) are fully reinitialized when resetting the Wasm instance. This is because
54+
the workerd runtime will instantiate exported classes, which would then be associated with the Wasm instance. So tracking and reinitializing these exported classes was necessary.
55+
56+
This approach is then all that is needed to provide full panic recovery for Rust Workers. Requests in progress during a panic will provide 500 errors, but the worker will then instantly recover for future requests with an instant reset.
57+
58+
Of course we never want panics, but when they do happen they are isolated and can be investigated further from the error logs - avoiding broader service disruption.
59+
60+
## WebAssembly Exception Handling
61+
62+
In future, we would like to see full support for recoverable panics without even needing reinitialization at all.
63+
64+
With the [WebAssembly Exception Handling](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md) proposal part of the newly announced [WebAssembly 3.0](https://webassembly.org/news/2025-09-17-wasm-3.0/) specification,
65+
it would actually be possible to fully unwind panics as normal JS errors. Concurrent requests would no longer fail at all, and all state would remain just fine.
66+
67+
This would be a larger Wasm Bindgen initiative, but a very useful one to explore further.
68+
69+
**We're making significant improvements to the reliability of [Rust Workers](https://github.com/cloudflare/workers-rs). Join us in `#rust-on-workers` on the [Cloudflare Developers Discord](https://discord.gg/cloudflaredev) to stay updated.**

0 commit comments

Comments
 (0)