xstate icon indicating copy to clipboard operation
xstate copied to clipboard

Bug: Delays are not properly restored when machine created from snapshot

Open jeromegn opened this issue 6 months ago • 3 comments

XState version

XState version 5

Description

When using delays (after: { 1000: "myTarget" }), if the state machine is persisted during a delay and then restored by re-creating it from the snapshot, then the delay will never trigger.

Seems like the delay information is lost when snapshotting.

I've worked around it by using a fromPromise actor with a promise resolving after a setTimeout. The input of that actor is a deadline computed when it is created (Date.now() + delay in ms).

Expected result

The delay should be resumed and possibly trigger its resolution condition if it is past the expected time it should've completed.

Actual result

The delay never resolves and the state machine is stuck forever.

Reproduction

I didn't prepare any, but should be easy?

Additional context

No response

jeromegn avatar Jul 13 '25 18:07 jeromegn

This hasn't been implemented yet; it's a bit tricky because there's no one-size-fits-all solution. There's (at least?) 3 possible ways it can resume:

  • Resume from start time: end at the previous end time, as if the delay was still active
  • Resume from remaining time: as if time "froze"
  • Restart delay
Image

davidkpiano avatar Jul 14 '25 04:07 davidkpiano

Yes, that's true!

I was thinking making it configurable with a good default (principle of least surprise) would be ideal. Each would store different information to prevent getting stuck on snapshot restore (could be start time, end time, some boolean or something else).

The problem with this is that persistence's caveats aren't really documented. Is it not a feature that's used very much? For a while restoring was completely broken if a machine had children actors. I can only assume other such bugs are lurking.

jeromegn avatar Jul 14 '25 11:07 jeromegn

Yeah, restoring from a snapshot is also tricky. A better solution I'd like to promote is event sourcing, since that would lead to a more accurate restoration of state.

davidkpiano avatar Jul 15 '25 08:07 davidkpiano