A failed operation raises ucall.Error, a RuntimeError whose status is the ucall.Status it reported and whose message is a static detail beside it.
Each failing status raises a subclass of its own, named after the status, such as ucall.ConnectionFailedError or ucall.NotFoundError.
Where a built-in exception names the same fault, the subclass derives it too: ConnectionError for connection failures, TimeoutError, MemoryError, OSError, ValueError for invalid or malformed input, KeyError, NotImplementedError, OverflowError and BlockingIOError. str(error) joins the two, as in “CONNECTION_FAILED: connection-failed”.
Arguments of the wrong type raise TypeError, a key of the wrong length or an unknown enum name raises ValueError, and a reply while views over the body are alive raises BufferError.
ucall.Status, Backend, CPUClass, Security, Verb, BodyDelivery and LogLevel are enum.IntEnum classes, and every argument taking one also takes its name in any case, with ”-” or ”_” between words. ucall.Status.from_name("out-of-memory") reads a status back from the spelling the library gives it, ucall.version() numbers the linked library, and ucall.__version__ spells it with any candidate suffix.
A submitted call that fails completes with that status in Completed.status, such as CONNECTION_FAILED, CONNECTION_CLOSED, TIMEOUT, HANDSHAKE_FAILED or PEER_REJECTED, and HTTP error statuses are ordinary responses.
On the serving side, failures become replies rather than exceptions: 400 for parameters that do not bind, 500 for a handler that raised or a request released unanswered.