Expected behavior when child actor throws an exception during pre-start

Hi All,

I noticed a change in the behavior when an exception thrown during pre-start after upgrading to Akka 2.6.20 from Akka 2.6.2. In Akka 2.6.2, when a child actor is being created and an unhandled exception is thrown during pre-start, my application keeps running into ActorInitializationException and tries to recreate the actor every time. The exception is handled by my supervision strategy and does not cause the parent actor or the application to stop. However, in Akka 2.6.20, once ActorInitializationException occurs, Akka runs into an assertion error in fault handling. This assertion error is then escalated to the parent actors and stops the application with the message “guardian failed, shutting down system”.

I suspect this behavior change is due to #27614. The assertion assert(perpetrator == self) fails because the perpetrator (FaultHandling.scala#L65) is null, indicating that _failed is something other than FailedRef. In my case _failed is FailedFatally when the assertion fails.

A NonFatal exception (ActorCell.scala#L653) causes _failed to be set to FailedFatally. Unfortunately, _failed always remains FailedFatally because transitions from FailedFatally to any other state is not allowed(FaultHandling.scala#L70). As a result, handleInvokeFailure(FaultHandling.scala#L211) can’t set _failed to the self actor ref like it previously could. Thus, my application now runs into the assertion error and eventually stops once the assertion error propagates to the parent actors.

I am trying to understand if this was added as a feature. If it’s a feature, how should the parent actor be handling the assertion error?

Thank you

I can’t reproduce this with Akka 2.9.3, if you could try on bumping your Akka version to see if it sorts the issue, and if it still fails with current Akka releases, provide us with a minimal reproducer (a test class ideally) that would be good.

Apologies for not including reproducible code.

Here’s a simple actor system that runs into the assertion error in Akka 2.6.20 but not in Akka 2.6.2.


public class Parent extends AbstractActor {

    private static SupervisorStrategy myStrategy = new OneForOneStartegy(5, Duration.create("1 minute"), e -> {
        if (e instanceof ActorInitializationException) {
            return SupervisorStrategy.restart();
        } else {
            SupervisorStrategy.escalate();
        }
    });

    @Override
    public SupervisorStrategy SupervisorStrategy() {
        return myStrategy;
    }

    @Override
    public void preStart() {
        this.getContext().actorOf(Props.create(Child.class), "child");
    }

    @Override
    public Receive createReceive() {
        return this.emptyBehavior();
    }
}
public class Child extends AbstractActor {

    @Override
    public void preStart() {
        throw new Exception("Test Exception");
    }

    @Override
    public Receive createReceive() {
        return this.emptyBehavior();
    }
}
public class TestSystem {

    public static void main(String[] args) {
        ActorSystem actorSystem = ActorSystem.create("TestActorSystem");
        
        ActorRef parent = actorSystem.actorOf(Props.create(Parent.class), "parent");

    }
}```

Thanks, I can confirm this is a regression bug, present in current Akka as well, likely introduced by the optimizations you guessed.

I’ve created Supervising ActorInitializationException broken when error is from preStart · Issue #32436 · akka/akka · GitHub to track fixing the bug.