Errors¶
Errors in CAF have a code and a category, similar to std::error_code
and
std::error_condition
. Unlike its counterparts from the C++ standard library,
error
is platform-neutral and serializable.
Class Interface¶
Constructors |
|
|
Constructs an error with given error code. |
|
Constructs an error with given error code and additional context. |
Observers |
|
|
Returns the error code as 8-bit integer. |
|
Returns the type ID of the Enum type used to construct this error. |
|
Returns additional context information |
|
Returns |
Add Custom Error Categories¶
Adding custom error categories requires these steps:
Declare an enum class of type
uint8_t
with error codes starting at 1. CAF always interprets the value 0 as no error.Assign a type ID to your enum type.
Specialize
caf::is_error_code_enum
for your enum type. For this step, CAF offers the macroCAF_ERROR_CODE_ENUM
to generate the boilerplate code necessary.
The following example illustrates all these steps for a custom error code enum
called math_error
.
enum class math_error : uint8_t {
division_by_zero = 1,
};
std::string to_string(math_error x) {
switch (x) {
case math_error::division_by_zero:
return "division_by_zero";
default:
return "-unknown-error-";
}
}
bool from_string(std::string_view in, math_error& out) {
if (in == "division_by_zero") {
out = math_error::division_by_zero;
return true;
} else {
return false;
}
}
bool from_integer(uint8_t in, math_error& out) {
if (in == 1) {
out = math_error::division_by_zero;
return true;
} else {
return false;
}
}
template <class Inspector>
bool inspect(Inspector& f, math_error& x) {
return caf::default_enum_inspect(f, x);
}
CAF_BEGIN_TYPE_ID_BLOCK(divider, first_custom_type_id)
CAF_ADD_TYPE_ID(divider, (math_error))
CAF_END_TYPE_ID_BLOCK(divider)
CAF_ERROR_CODE_ENUM(math_error)
Default Error Codes¶
The enum type sec
(for System Error Code) provides many error codes for
common failures in actor systems:
/// SEC stands for "System Error Code". This enum contains error codes for
/// ::actor_system and its modules.
enum class sec : uint8_t {
/// No error.
none = 0,
/// Indicates that an actor dropped an unexpected message.
unexpected_message = 1,
/// Indicates that a response message did not match the provided handler.
unexpected_response,
/// Indicates that the receiver of a request is no longer alive.
request_receiver_down,
/// Indicates that a request message timed out.
request_timeout,
/// Indicates that requested group module does not exist.
no_such_group_module = 5,
/// Unpublishing or connecting failed: no actor bound to given port.
no_actor_published_at_port,
/// Connecting failed because a remote actor had an unexpected interface.
unexpected_actor_messaging_interface,
/// Migration failed because the state of an actor is not serializable.
state_not_serializable,
/// An actor received an unsupported key for `('sys', 'get', key)` messages.
unsupported_sys_key,
/// An actor received an unsupported system message.
unsupported_sys_message = 10,
/// A remote node disconnected during CAF handshake.
disconnect_during_handshake,
/// Tried to forward a message via BASP to an invalid actor handle.
cannot_forward_to_invalid_actor,
/// Tried to forward a message via BASP to an unknown node ID.
no_route_to_receiving_node,
/// Middleman could not assign a connection handle to a broker.
failed_to_assign_scribe_from_handle,
/// Middleman could not assign an acceptor handle to a broker.
failed_to_assign_doorman_from_handle = 15,
/// User requested to close port 0 or to close a port not managed by CAF.
cannot_close_invalid_port,
/// Middleman could not connect to a remote node.
cannot_connect_to_node,
/// Middleman could not open requested port.
cannot_open_port,
/// A C system call in the middleman failed.
network_syscall_failed,
/// A function received one or more invalid arguments.
invalid_argument = 20,
/// A network socket reported an invalid network protocol family.
invalid_protocol_family,
/// Middleman could not publish an actor because it was invalid.
cannot_publish_invalid_actor,
/// A remote spawn failed because the provided types did not match.
cannot_spawn_actor_from_arguments,
/// Serialization failed because there was not enough data to read.
end_of_stream,
/// Serialization failed because no CAF context is available.
no_context = 25,
/// Serialization failed because CAF misses run-time type information.
unknown_type,
/// Serialization of actors failed because no proxy registry is available.
no_proxy_registry,
/// An exception was thrown during message handling.
runtime_error,
/// Linking to a remote actor failed because actor no longer exists.
remote_linking_failed,
/// Subscribing to a stream failed because it was invalid.
invalid_stream = 30,
/// Subscribing to a stream failed because it can only be subscribed to once.
cannot_resubscribe_stream,
/// A stream was aborted by the hosting actor, usually because it terminated.
stream_aborted,
/// A function view was called without assigning an actor first.
bad_function_call = 40,
/// Feature is disabled in the actor system config.
feature_disabled,
/// Failed to open file.
cannot_open_file,
/// A socket descriptor argument is invalid.
socket_invalid,
/// A socket became disconnected from the remote host (hang up).
socket_disconnected,
/// An operation on a socket (e.g. `poll`) failed.
socket_operation_failed = 45,
/// A resource is temporarily unavailable or would block.
unavailable_or_would_block,
/// Connection refused because of incompatible CAF versions.
incompatible_versions,
/// Connection refused because of incompatible application IDs.
incompatible_application_ids,
/// Received a malformed message from another node.
malformed_message,
/// The middleman closed a connection because it failed to serialize or
/// deserialize a payload.
serializing_basp_payload_failed = 50,
/// The middleman closed a connection to itself or an already connected node.
redundant_connection,
/// Resolving a path on a remote node failed.
remote_lookup_failed,
/// Serialization failed because actor_system::tracing_context is null.
no_tracing_context,
/// No request produced a valid result.
all_requests_failed,
/// Deserialization failed because an invariant got violated after reading
/// the content of a field.
field_invariant_check_failed = 55,
/// Deserialization failed because a setter rejected the input.
field_value_synchronization_failed,
/// Deserialization failed because the source announced an invalid type.
invalid_field_type,
/// Serialization failed because a type was flagged as unsafe message type.
unsafe_type,
/// Serialization failed because a save callback returned `false`.
save_callback_failed,
/// Deserialization failed because a load callback returned `false`.
load_callback_failed = 60,
/// Converting between two types failed.
conversion_failed,
/// A network connection was closed by the remote side.
connection_closed,
/// An operation failed because run-time type information diverged from the
/// expected type.
type_clash,
/// An operation failed because the callee does not implement this
/// functionality.
unsupported_operation,
/// A key lookup failed.
no_such_key = 65,
/// An destroyed a response promise without calling deliver or delegate on it.
broken_promise,
/// Disconnected from a BASP node after reaching the connection timeout.
connection_timeout,
/// Signals that an actor fell behind a periodic action trigger. After raising
/// this error, an @ref actor_clock stops scheduling the action.
action_reschedule_failed,
/// Attaching to an observable failed because the target is invalid.
invalid_observable,
/// Attaching to an observable failed because the target already reached its
/// maximum observer count.
too_many_observers = 70,
/// Signals that an operation failed because the target has been disposed.
disposed,
/// Failed to open a resource.
cannot_open_resource,
/// Received malformed data.
protocol_error,
/// Encountered faulty logic in the program.
logic_error,
/// An actor tried to delegate a message to an invalid actor handle.
invalid_delegate = 75,
/// An actor tried to delegate a message to an invalid actor handle.
invalid_request,
/// Signals that `future::get` timed out.
future_timeout,
/// Received invalid UTF-8 encoding.
invalid_utf8,
/// A downstream operator failed to process inputs on time.
backpressure_overflow,
/// Signals that a supervisor failed to start a new worker because too many
/// workers failed in a short period of time.
too_many_worker_failures = 80,
};
Default Exit Reasons¶
A special kind of error codes are exit reasons of actors. These errors are
usually fail states set by the actor system itself. The two exceptions are
exit_reason::user_shutdown
and exit_reason::kill
. The former is used in
CAF to signalize orderly, user-requested shutdown and can be used by programmers
in the same way. The latter terminates an actor unconditionally when used in
send_exit
, even for actors that override the default handler (see
Exit Messages).
/// This error category represents fail conditions for actors.
enum class exit_reason : uint8_t {
/// Indicates that an actor finished execution without error.
normal = 0,
/// Indicates that the exit reason for this actor is unknown, i.e.,
/// the actor has been terminated and no longer exists.
unknown,
/// Indicates that an actor pool unexpectedly ran out of workers.
out_of_workers,
/// Indicates that an actor was forced to shutdown by a user-generated event.
user_shutdown,
/// Indicates that an actor was killed unconditionally.
kill,
/// Indicates that an actor finished execution because a connection
/// to a remote link was closed unexpectedly.
remote_link_unreachable,
/// Indicates that an actor was killed because it became unreachable.
unreachable
};