cloudflare / cloudflare/workerd

Bug: Durable Object alarm firing under `durableObjectStorage = (inMemory = void)` crashes the workerd process

Open
#7,191 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

## Summary

Any Durable Object alarm that FIRES while the worker is configured with
`durableObjectStorage = (inMemory = void)` terminates the entire workerd
process with an uncaught KJ exception. The alarm handler body is irrelevant
(an empty handler crashes identically).

Local-dev configuration surface; production DOs are disk-backed.

## Environment

- workerd 1.20260826.1, macOS arm64 (release build) and linux arm64 (ASAN build) — both reproduce identically
- `compatibilityDate`: 2026-08-26 and 2024-09-23 (both reproduce)

## Repro

1. Config: one service, one DO class, `durableObjectStorage = (inMemory = void)`.
2. Worker arms an alarm: `await this.ctx.storage.setAlarm(Date.now() + 40);`
3. Alarm handler: may be completely empty (`return;`).
4. When the alarm fires, workerd exits:

```
*** Fatal uncaught kj::Exception: kj/async.c++:2202: failed: Promise callback destroyed itself.
```

## Discrimination

- With `durableObjectStorage = (localDisk = "")` the same alarm fires and completes cleanly.
- `deleteAlarm()` before the scheduled time does not crash.
- `ctx.abort()` inside the handler does not crash (the DO resets instead); with the default options no retry was observed post-reset.

## Expected

An alarm firing under in-memory storage should behave like the disk-backed
path (handler runs or a well-typed JS error surfaces), never abort the whole
process.

## Notes

Happy to send the exact single-file config + worker used, or open a PR with a repro test if pointed at the right test layout.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the crash with a Durable Object alarm and durableObjectStorage = (inMemory = void), then compare it with the localDisk configuration that completes cleanly. Trace the alarm-firing path in workerd and add a regression test if the relevant test layout is identified; done means the in-memory alarm handler runs or reports a typed JavaScript error without terminating the process.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.