Skip to content

Commit 87bf21c

Browse files
bchapuisclaude
andcommitted
Fix workflow state lost after Durable Object hibernation
Make requireInitialized() async so it can reload workflow state from the database when the DO wakes from hibernation, instead of throwing an error. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c438166 commit 87bf21c

1 file changed

Lines changed: 10 additions & 9 deletions

File tree

apps/api/src/durable-objects/workflow-agent.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export class WorkflowAgent extends Agent<Bindings, WorkflowAgentState> {
148148
message: string | ArrayBuffer
149149
): Promise<void> {
150150
try {
151-
this.requireInitialized();
151+
await this.requireInitialized();
152152

153153
if (typeof message !== "string") {
154154
connection.close(1003, "Binary messages not supported");
@@ -265,21 +265,22 @@ export class WorkflowAgent extends Agent<Bindings, WorkflowAgentState> {
265265
}
266266

267267
/**
268-
* Throws if workflow state is not loaded. Used by onMessage which always
269-
* runs after onConnect has loaded state — failure here means the DO
270-
* woke from hibernation and Agent state was lost.
268+
* Ensures workflow state is loaded. If the DO woke from hibernation and
269+
* in-memory state was lost, attempts to reload from the database using
270+
* the persisted Agent state.
271271
*/
272-
private requireInitialized(): void {
272+
private async requireInitialized(): Promise<void> {
273273
if (this.workflowState) return;
274274

275275
const { workflowId, userId } = this.state ?? {};
276276
if (!workflowId || !userId) {
277277
throw new Error("Session state lost. Please refresh the page.");
278278
}
279-
// State exists in Agent storage but not loaded into memory yet.
280-
// This shouldn't happen in practice since onConnect always loads first,
281-
// but if it does, the throw above gives a clear error.
282-
throw new Error("Workflow state not loaded. Reconnect to reload.");
279+
280+
// DO woke from hibernation — reload state from database
281+
if (await this.tryLoadState(workflowId, userId)) return;
282+
283+
throw new Error("Failed to reload workflow state after hibernation.");
283284
}
284285

285286
/**

0 commit comments

Comments
 (0)