xan_actor/error.rs
1use thiserror::Error;
2
3/// All errors surfaced by the actor system.
4///
5/// Variants gated on `multi-node` only exist when that feature is enabled.
6/// Most user-facing call sites return `Result<_, ActorError>`; match on the
7/// variant when you need to distinguish (e.g. retry on `ActorNotReady` vs.
8/// give up on `AddressNotFound`).
9#[derive(Error, Debug)]
10pub enum ActorError {
11 /// `oneshot::Receiver::await` failed (sender dropped before sending).
12 /// Typically means the actor task died between accepting the message
13 /// and producing a reply.
14 #[error(transparent)]
15 OneshotRecv(#[from] tokio::sync::oneshot::error::RecvError),
16 /// Channel send failed — the receiver was dropped. Indicates the
17 /// target mailbox/loop has shut down. Same variant for both the
18 /// bounded and unbounded mpsc backends.
19 #[error("Failed to send on channel: {0}")]
20 ChannelSend(String),
21 /// Channel `recv` returned `None` — all senders are gone. Same
22 /// variant for both backends.
23 #[error("Failed to recv from channel")]
24 ChannelRecv,
25 /// A timed `send_and_recv` (via
26 /// [`ActorSystem::send_and_recv_with_timeout`] or
27 /// [`ActorSystem::send_and_recv_without_tx_cache_with_timeout`]) did
28 /// not receive its reply within the configured duration. Common
29 /// cause in multi-node mode: the remote peer died or the broker
30 /// dropped the in-flight request.
31 ///
32 /// [`ActorSystem::send_and_recv_with_timeout`]: crate::ActorSystem::send_and_recv_with_timeout
33 /// [`ActorSystem::send_and_recv_without_tx_cache_with_timeout`]: crate::ActorSystem::send_and_recv_without_tx_cache_with_timeout
34 #[error("Operation timed out after {0:?}")]
35 Timeout(std::time::Duration),
36 /// `address_regex` failed to compile (broadcast / restart / unregister).
37 #[error(transparent)]
38 AddressRegexError(#[from] regex::Error),
39
40 /// Tried to register an actor at an address that's already taken on
41 /// this node (and not a restart). Re-registration with the same
42 /// address fails until the existing entry is unregistered.
43 #[error("Address {0} already exists")]
44 AddressAlreadyExist(String),
45 /// `send` / `send_and_recv` / `run_job` could not find the address in
46 /// the local actor map. With `multi-node` this is the local-side
47 /// failure mode after the routing check decides the call is local.
48 #[error("Address {0} not found")]
49 AddressNotFound(String),
50 /// The address exists but the actor's lifecycle is not yet `Receiving`
51 /// after the retry budget (10 × 100 ms). Usually means the actor is
52 /// still in `Starting` / `Restarting`.
53 #[error("Actor that's address is {0} not ready")]
54 ActorNotReady(String),
55 /// Reserved for cases where cloning an actor state fails. Currently
56 /// not produced by the runtime.
57 #[error("Actor clone failed: {0}")]
58 CloneFailed(String),
59 /// `Actor::register` could not reach `actor_system_loop` after 10
60 /// retries — the system is wedged or shutting down.
61 #[error("Unhealthy ActorSystem")]
62 UnhealthyActorSystem,
63 /// Downcast from `Arc<dyn Any>` / `Box<dyn Any>` to the expected
64 /// concrete message or result type failed. Usually means a `send::<T>`
65 /// (or `send_and_recv::<T>`) was routed to an address whose actor type
66 /// doesn't match `T`.
67 #[error("Message type mismatch")]
68 MessageTypeMismatch,
69
70 /// Underlying xanq client IO failed (e.g. broker disconnected, TCP
71 /// reset, broker connect timed out).
72 #[cfg(feature = "multi-node")]
73 #[error("Inter-node IO error: {0}")]
74 InterNodeIo(String),
75 /// `xancode::Codec::decode` failed when turning bytes back into
76 /// `<T as Actor>::Message` (receiver side) or `<T as Actor>::Result`
77 /// (caller side).
78 #[cfg(feature = "multi-node")]
79 #[error("Inter-node decode error: {0}")]
80 InterNodeDecode(String),
81 /// The receiving node got an envelope for an actor type with no
82 /// matching `register_for_inter_node!` entry in its inventory
83 /// registry. Fix by adding the macro call at module scope on both
84 /// nodes.
85 #[cfg(feature = "multi-node")]
86 #[error("Inter-node decoder not registered for actor type {0}")]
87 InterNodeDecoderMissing(String),
88 /// The peer node responded with `ResponseOutcome::Err`, or the
89 /// pending-response channel was dropped (peer crashed mid-call). The
90 /// payload is the original error string from the peer.
91 #[cfg(feature = "multi-node")]
92 #[error("Inter-node remote error: {0}")]
93 InterNodeRemote(String),
94 /// Attempted a cross-node send on an `ActorSystem` created with
95 /// `broker_addr = None`. Provide a broker address (or keep all
96 /// addresses on the local node).
97 #[cfg(feature = "multi-node")]
98 #[error("Inter-node not configured")]
99 InterNodeNotConfigured,
100 /// `Actor::register` was called with `address.node` not equal to the
101 /// system's own `node_name`. Each node can only host actors whose
102 /// addresses claim that node.
103 #[cfg(feature = "multi-node")]
104 #[error("Address {0} is not owned by this node")]
105 AddressNotOwned(String),
106}