Skip to content

[Bug] An all-for-one restart resumes a sibling that is already terminating, leaving a running actor whose child set can never finalise #923

Description

@pathosDev

Problem

An AllForOneStrategy restart snapshots every child regardless of state, including a sibling that is already terminating. That sibling is then handed a recreate, and onRecreate unconditionally resumes its mailbox and sets its state back to running — after its own children have already been sent terminate.

The result is an actor that is running again but whose onChildTerminated will now bail, because the guard there expects state terminating. It has a child set it can never finalise, so it can never terminate.

Evidence

The snapshot takes every child, unfiltered:

src/internal/ActorCell.ts:1143-1145
    const affected = strategy.scope === 'all-for-one'
      ? Array.from(this._children.values())
      : [child];

onRecreate then resumes and re-runs it, with no check on the prior state:

src/internal/ActorCell.ts:942-946
      this.behaviorStack = [(m: TMessage) => next.onReceive(m)];
      await next.postRestart(cause);
      this.mailbox.resume();
      this.state = 'running';

and onChildTerminated (src/internal/ActorCell.ts:1195) returns early when the state is no longer terminating, so the pending child terminations never complete the parent's own teardown.

Proposal

Filter the all-for-one snapshot to children in a restartable state (running / suspended), and make onRecreate refuse to resume a cell that is terminating or terminated — a restart directive arriving for an actor that is already on its way out should be dropped, not honoured.

Acceptance sketch

  • An all-for-one restart does not send recreate to a terminating sibling.
  • onRecreate on a terminating cell is a no-op rather than a resume.
  • A test covers "one child fails while another is stopping" under AllForOneStrategyAllForOneStrategy currently has no behavioural test at all (see the sibling test-coverage issue in this batch).

Verification status

Found in the ten-lens production-readiness review of 2026-08-05 (v0.13.0) and re-verified before filing: confirmed by reading the three cited sites. Not reproduced at runtime — constructing the interleaving reliably needs a deterministic scheduler, which is itself one of the gaps this batch records.

Part of the production-readiness review batch — tracked in #913.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: mediumUseful, not urgentproduction-goalBlocks or defines the path to production readiness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions