Skip to content

🐛 Bug: ctx.id.name is undefined in DO alarm handlers after the actor is evicted (local dev) #6850

Description

@apeacock1991

Summary

When a Durable Object created via idFromName()/getByName() runs its alarm() handler, ctx.id.name is undefined if the DO instance was evicted from memory before the alarm fired. Normal requests are unaffected because the caller re-derives the name-bearing ID on each call.

Root cause

The local AlarmScheduler persists only the hex actor ID, not the name:

-- src/workerd/server/alarm-scheduler.c++
CREATE TABLE IF NOT EXISTS _cf_ALARM (
  actor_id TEXT PRIMARY KEY,
  scheduled_time INTEGER
) WITHOUT ROWID;

The name is a one-way HMAC into the ID bytes, so it can't be recovered from the hex ID. When the alarm fires and the actor isn't resident, server.c++ reconstructs it via idFromString(), which produces a nameless ActorId:

// src/workerd/server/server.c++ (AlarmScheduler::GetActorFn)
Worker::Actor::Id id = idFactory->idFromString(kj::mv(idStr));  // name is always kj::none

That nameless ID is used to build the Worker::Actor, so ctx.id.name is empty. While the actor is still warm, the original name-bearing ID is reused and it works.

Reproduction

  1. getByName("foo") → set an alarm more than ~10s out (past the idle-eviction window), or restart the process.
  2. In alarm(), read this.ctx.id.name → undefined (expected "foo").

Suggested fix

Persist the name alongside actor_id in _cf_ALARM, thread it through AlarmScheduler/GetActorFn, and reconstruct via the existing idFromRaw(bytes, name) overload instead of idFromString().

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions