By "error" I usually mean some kind of crash (exception/termination/disconnection).
Let's imagine that two actors are interacting. Actor number 1 is observing assertions matching pattern (A, *), and actor number 2 then asserts (A, 123).
Actor 1 then receives an event indicating that a tuple (A, 123) has been asserted.
Now, imagine Actor 2 crashes. The Syndicated Actor Model ensures that all its assertions are cleanly retracted. This causes an event for Actor 1 saying that (A, 123) has been retracted again.
So you can see this as a communication of the crash! But what it doesn't do is indicate any detail about why the retraction happened. It could have been a deliberate retraction, or a crash due to any number of reasons, or a timeout in some intermediate transport layer causing disconnection, etc etc.
There are other uses of "error": for example, your "key not found" status. There, the protocol for interaction among actors should include an explicit assertion or message. This is the kind of "error handling" seen in languages like ML, Haskell, Rust, and so on, where errors are (non-crash) values. It's a good strategy.
At a slight tangent, there's one thing Syndicate can do here that other (non-actor) systems cannot, and that's "key not found yet". For that, silence is a tacit indicator of no result. For example, you could assert interest in (Map, "mykey", *) tuples. If and when any such appear or disappear, you get notified. Because time is involved, receiving no message is an indicator of "key not found yet".
There are a couple of approaches here. If there is a moment when it's known that no matches will be found, then either an actor can assert something to this effect or the querier can wait "long enough" and then move on. For the former, if there's some actor in charge of maintaining an authoritative copy of the collection concerned, they may assert some "no match" record. For the latter, the SAM includes a "sync" action which is essentially a no-op roundtrip to some target. Once the sync returns, you know all previous assertions must have been seen by that target, and if you know something about how the target operates, it might be safe to conclude no response will be forthcoming.
Let's imagine that two actors are interacting. Actor number 1 is observing assertions matching pattern (A, *), and actor number 2 then asserts (A, 123).
Actor 1 then receives an event indicating that a tuple (A, 123) has been asserted.
Now, imagine Actor 2 crashes. The Syndicated Actor Model ensures that all its assertions are cleanly retracted. This causes an event for Actor 1 saying that (A, 123) has been retracted again.
So you can see this as a communication of the crash! But what it doesn't do is indicate any detail about why the retraction happened. It could have been a deliberate retraction, or a crash due to any number of reasons, or a timeout in some intermediate transport layer causing disconnection, etc etc.
There are other uses of "error": for example, your "key not found" status. There, the protocol for interaction among actors should include an explicit assertion or message. This is the kind of "error handling" seen in languages like ML, Haskell, Rust, and so on, where errors are (non-crash) values. It's a good strategy.
At a slight tangent, there's one thing Syndicate can do here that other (non-actor) systems cannot, and that's "key not found yet". For that, silence is a tacit indicator of no result. For example, you could assert interest in (Map, "mykey", *) tuples. If and when any such appear or disappear, you get notified. Because time is involved, receiving no message is an indicator of "key not found yet".