Status codes and result types for RPC operations
Learn more: Error handling
Classes | |
| class | pw::rpc2::RpcStatus |
Typedefs | |
| template<typename T > | |
| using | pw::rpc2::RpcResult = ::pw::Result< T, RpcStatus > |
A value of type T, or the RpcStatus explaining why there is none. | |
|
strong |
The 8-bit error code carried by an ERROR_TERMINAL packet.
Every code names exactly one condition, so the peer's logs say precisely why a call ended. ProtocolError is internal: no public API takes or returns one. A received code becomes a status in one place, through PeerErrorToRpcStatus().
The top two bits of each code are its origin, which determines which endpoint may send it (see CodeOrigin):
0x00–0x3F: Either endpoint (except kNone, which is never sent).0x40–0x7F: Server only.0x80–0xBF: Client only (none are defined).0xC0–0xFF: Reserved.These are the codes protocol version 1 defines. An endpoint never sends a code that the negotiated version does not define, so a receiver treats any code it does not recognize as a protocol violation. A later version that adds codes sends an older peer the closest code that peer's version defines.
| Enumerator | |
|---|---|
| kNone | No error. Never sent; |
| kInternal | A bug in the RPC implementation. |
| kCancelled | Application code cancelled the call: explicitly with |
| kMethodTypeMismatch | A packet does not match the method's type. On the server, a unary or server-streaming call must be started by a packet that carries the request message and closes the client's stream. On the client, a unary or client-streaming call must be answered by a single packet that carries the response message and terminates the RPC. |
| kReceivedPacketForWrongEndpoint | The endpoint received a packet type that only its own role may send (a server received a server-to-client packet, or a client received a client-to-server packet). |
| kReceivedPacketForUnknownCall | The endpoint received a non-terminal packet for a call ID it does not know about. |
| kUnknownService | The requested service is not registered on the server. |
| kUnknownMethod | The requested method is not registered on the target service. |
| kReceivedDuplicateStart | The server received a start packet for a call ID that is still active. Both calls end. |
| kInvalidRequestPayload | The request payload could not be decoded. |
| kFailedToAllocateCall | The server could not allocate state for the call. The method never ran. |
| kFailedToAllocateCallResourcesWhileRunning | An allocation failed after the method started. |
| kServiceUnregistered | The service was unregistered while the call was running. The C++ server does not support unregistering services, so it never sends this. |
| kDroppedWithoutResponse | A |
| kMethodReturnedWithoutFinishing | The method's future completed while a |
|
strong |
The outcome of a pw_rpc2 operation, expressed as what the caller should do next. Use RpcStatus objects instead of RpcCode.
Each code maps to one distinct action, so the code alone is enough to decide how to respond. The precise cause of an error is not part of the status: pw_rpc2 logs it where it is detected.
RpcCode values are never sent on the wire. Endpoints exchange more precise error codes, which the receiver converts to an RpcCode. The numeric values may change.
| Enumerator | |
|---|---|
| kOk | The operation succeeded. Action: Continue. |
| kEndOfStream | The peer finished its stream and every message it sent has been read. Not a failure. For a client, the RPC finished successfully. Action: Stop reading. |
| kCancelled | Application code on either side ended the call, explicitly (with Action: Stop work on the call. Don't retry automatically: application logic chose to end it. |
| kClosed | You closed the Action: Up to you; you closed this call. |
| kWriteClosed | This call's outbound direction is closed. The call itself may still be open. Action: Stop writing. If a response or more messages are expected, keep reading. |
| kDisconnected | The connection is gone or could not be made, for a reason that a new connection can fix. Whether the peer processed in-flight calls is unknown. Action: Create a new |
| kResourceExhausted | This endpoint could not allocate memory for the operation. The peer was not involved. Action: Free local resources (finish or drop other calls, or run fewer at once), then retry. Backing off against the server won't help. |
| kUnavailable | The server could not take the call right now. The method never ran. Action: Retry later with backoff. Retrying is safe even for methods that are not idempotent. |
| kAborted | The server started the call, then ended it for a reason outside the method's control. The method may have partly run. Action: Retry only if the method is idempotent; otherwise, report the failure. |
| kUnimplemented | The server does not offer this method in the form the client expects. Action: Don't retry against this server. Fall back (for example, to an older API or a feature-detected path), or fix the deployment or schema mismatch. |
| kMessageTooLarge | An outbound message is larger than the transport or reservation allows. Nothing was sent, and the call is still open. Action: Send a smaller message (for example, split it), or raise the reservation or transport limit. |
| kDataError | A message could not be encoded or decoded. Action: Don't resend the same message unchanged; fix it or the schema mismatch. What remains of the call depends on where the error occurred:
|
| kProtocolError | An endpoint broke the protocol, the endpoints' protocol versions are incompatible, or an RPC implementation has a bug. If the error closed the connection, later calls on the same Action: Nothing fixes this at runtime: reconnecting and retrying won't help. Log or report it; it needs a code or deployment fix. |