This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
RPC Service Errors
Relevant source files
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs
- extensions/muxio-rpc-service-caller/tests/prebuffered_caller_tests.rs
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs
- extensions/muxio-wasm-rpc-client/tests/prebuffered_integration_tests.rs
Purpose and Scope
This document describes the error handling system used by the RPC framework layer in rust-muxio. It covers the RpcServiceError type, its variants, error codes, and how errors propagate between client and server. For information about lower-level transport errors and connection failures, see Transport Errors. For details on how errors are created in service handlers, see Service Endpoint Interface.
Error Type Hierarchy
The RPC framework uses a structured error system centered around the RpcServiceError enum, which distinguishes between protocol-level RPC errors and underlying transport errors.
Sources:
graph TB
RSE["RpcServiceError"]
RSE --> Rpc["Rpc(RpcServiceErrorPayload)"]
RSE --> Transport["Transport(io::Error)"]
Rpc --> Payload["RpcServiceErrorPayload"]
Payload --> Code["code: RpcServiceErrorCode"]
Payload --> Message["message: String"]
Code --> NotFound["NotFound"]
Code --> Fail["Fail"]
Code --> System["System"]
NotFound -.- NF_Desc["Method not registered\non server"]
Fail -.- Fail_Desc["Application-level\nerror from handler"]
System -.- Sys_Desc["Server panic or\ninternal error"]
- extensions/muxio-rpc-service-caller/tests/prebuffered_caller_tests.rs8
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs4
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs4
RpcServiceError Variants
The RpcServiceError type has two primary variants that separate RPC protocol errors from transport layer failures.
Rpc Variant
The Rpc variant wraps an RpcServiceErrorPayload and represents errors that occur at the RPC protocol layer. These errors are serialized and transmitted from the server to the client as part of the RPC protocol itself.
Structure:
code: AnRpcServiceErrorCodeenum indicating the error categorymessage: A human-readable error description string
Example usage from tests:
Sources:
Transport Variant
The Transport variant wraps a standard io::Error and represents errors that occur in the underlying transport layer, such as serialization failures or network issues that prevent the RPC from completing.
Example usage:
Sources:
RpcServiceErrorCode Values
The RpcServiceErrorCode enum defines standardized error categories used throughout the RPC system. Each code has specific semantics for how the error should be interpreted and potentially recovered from.
| Error Code | Meaning | Typical Scenario |
|---|---|---|
NotFound | The requested method ID is not registered on the server | Client calls a method that the server doesn't implement |
Fail | Application-level error returned by the handler | Business logic failure (e.g., "user not found", "invalid input") |
System | Internal server error or panic in the handler | Handler panicked, internal consistency error, or unexpected condition |
NotFound Error Code
Used when a client attempts to invoke an RPC method that the server has not registered. This typically indicates a version mismatch between client and server service definitions.
Test example:
Sources:
Fail Error Code
Used for application-level errors that are part of normal business logic. These errors are expected and recoverable.
Test example:
Sources:
System Error Code
Used for internal server errors, including handler panics or unexpected system failures. These typically indicate bugs or serious issues on the server side.
Test example:
Sources:
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs:114-150
- extensions/muxio-rpc-service-caller/tests/prebuffered_caller_tests.rs:197-200
sequenceDiagram
participant Client as "RpcCallPrebuffered\n::call()"
participant CallerIface as "RpcServiceCaller\nInterface"
participant Dispatcher as "RpcDispatcher"
participant Transport as "WebSocket"
participant ServerDisp as "Server\nRpcDispatcher"
participant Endpoint as "RpcServiceEndpoint\nInterface"
participant Handler as "Method Handler"
Client->>CallerIface: call_rpc_buffered(request)
CallerIface->>Dispatcher: Register request
Dispatcher->>Transport: Send RPC frames
Transport->>ServerDisp: Receive frames
ServerDisp->>Endpoint: dispatch by METHOD_ID
Endpoint->>Handler: invoke handler
Note over Handler: Handler returns\nErr("Addition failed")
Handler-->>Endpoint: Err(String)
Note over Endpoint: Convert to RpcServiceError::Rpc\nwith code=System
Endpoint-->>ServerDisp: Serialize error payload
ServerDisp-->>Transport: Send error response frames
Transport-->>Dispatcher: Receive error frames
Dispatcher-->>CallerIface: Deserialize error
CallerIface-->>Client: Err(RpcServiceError::Rpc)
Note over Client: Pattern match on error:\ncode and message available
Error Propagation Flow
This sequence diagram illustrates how errors propagate from a server-side handler back to the client, including serialization and protocol-level wrapping.
Sources:
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs:100-152
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:49-97
Error Creation on Server Side
Server-side handlers can return errors in multiple ways, all of which are converted to RpcServiceError by the endpoint interface.
Handler Return Types
Handlers registered via register_prebuffered return Result<Vec<u8>, E> where E implements Into<RpcServiceError>. The most common patterns are:
Returning a String error:
This automatically converts to RpcServiceError::Rpc with code: RpcServiceErrorCode::System.
Sources:
graph LR Request["RpcRequest\nmethod_id=12345"] --> Lookup["Endpoint method\nlookup"] Lookup -->|Not found| AutoError["Auto-generate\nRpcServiceError::Rpc"] AutoError --> ErrorPayload["RpcServiceErrorPayload\ncode=NotFound"] ErrorPayload --> Response["Send error response\nto client"]
Method Not Found Errors
When a client calls a method that isn't registered, the server's endpoint interface automatically generates a NotFound error without involving any handler:
Sources:
Error Handling on Client Side
Clients receive errors as part of the normal RPC response flow and must pattern match on the error type to handle different scenarios appropriately.
Pattern Matching on Error Codes
The recommended pattern for handling RPC errors is to match on the RpcServiceError variants and then examine the error code:
Sources:
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs:136-150
- extensions/muxio-rpc-service-caller/tests/prebuffered_caller_tests.rs:170-176
Error Propagation Through RpcCallPrebuffered
The RpcCallPrebuffered trait implementation automatically propagates errors from the underlying call_rpc_buffered method. It handles two levels of Result nesting:
- Outer Result : Represents transport-level success/failure
- Inner Result : Contains either decoded response or
RpcServiceError::Rpc
Sources:
Common Error Scenarios
Scenario 1: Unregistered Method Call
Situation: Client calls a method that the server doesn't have registered.
Error Flow:
- Client encodes request and sends to server
- Server dispatcher receives frames and extracts
METHOD_ID - Endpoint lookup fails to find handler
- Server automatically creates
RpcServiceError::Rpcwithcode: NotFound - Error is serialized and sent back to client
- Client receives and deserializes the error
Client-side result:
Sources:
Scenario 2: Handler Returns Application Error
Situation: Handler logic determines that the request cannot be fulfilled due to business logic constraints.
Error Flow:
- Server invokes handler with decoded request
- Handler returns
Err("validation failed") - Endpoint converts string to
RpcServiceError::Rpcwithcode: System - Error is serialized and transmitted
- Client receives error with code and message
Client-side result:
Sources:
- extensions/muxio-tokio-rpc-client/tests/prebuffered_integration_tests.rs:100-152
- extensions/muxio-wasm-rpc-client/tests/prebuffered_integration_tests.rs:144-227
Scenario 3: Deserialization Failure
Situation: Client successfully receives response bytes but fails to deserialize them into the expected type.
Error Flow:
- Server sends valid response bytes
- Client dispatcher reassembles payload
decode_responseclosure returnsio::Error- Error is wrapped as
RpcServiceError::Transport
Client-side result:
Sources:
Integration with Transport Layer
While this document focuses on RPC-level errors, it's important to understand how these errors interact with transport-level failures:
| Layer | Error Type | Scope |
|---|---|---|
| RPC Protocol | RpcServiceError::Rpc | Method not found, handler failures, application errors |
| Transport | RpcServiceError::Transport | Serialization, deserialization, io::Error |
| Connection | Connection state changes | Disconnection, reconnection (see Transport State Management) |
The separation ensures that RPC-level errors (which are part of the protocol) remain distinct from transport-level errors (which indicate infrastructure failures).
Sources:
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:1-99
- extensions/muxio-rpc-service-caller/tests/prebuffered_caller_tests.rs:1-213
Dismiss
Refresh this wiki
Enter email to refresh