Repository navigation
Conversation
Frando
force-pushed
the
Frando/error-cases-variants
branch
from
October 9, 2026 22:27
f551ec2 to
31543e7
Compare
Frando
marked this pull request as draft
October 9, 2026 22:33
Frando
marked this pull request as ready for review
October 12, 2026 08:50
Collaborator
|
🤖 In |
The codes were public constants, and code compared stream codes against them one by one. `ErrorCode` defines each code once, as its discriminant, with `to_code` and `from_code`, and converts into the `VarInt` that noq takes. The code and its docs use it everywhere instead of the constants, also for code 0. The behavior is the same.
Frando
force-pushed
the
Frando/error-cases-variants
branch
from
October 12, 2026 13:33
2745e94 to
5f07f08
Compare
…y them in Remote variants
irpc used the same codes for a bad request and for a bad channel message,
so a client could not tell a rejected request from a rejected response,
and every reset or stop from the peer reached the user as an `Io` error.
The error codes are now split into request codes (`RequestAborted`,
`RequestMaxSizeExceeded`, `RequestEncodeFailed`, `RequestDecodeFailed`)
and message codes (`MessageMaxSizeExceeded`, `MessageEncodeFailed`,
`MessageDecodeFailed`), and `ErrorCode` implements `Display`.
`SendError`, `oneshot::RecvError`, `mpsc::RecvError`, and `WriteError`
get a `Remote { code }` variant for a code that the peer reset or stopped
the stream with, and keep their own variants only for errors that this
side found: `MaxSizeExceeded`, `EncodeFailed`, and `DecodeFailed`.
`ReadRequestError` has `MaxSizeExceeded`, `Malformed`, and `DecodeFailed`.
`remote_code()` returns the code of a `Remote` error.
The server rejects a bad request with the request code on both streams and
when it closes the connection. A client that cannot encode its request
resets the stream with the request code. When the server skips a request
whose stream the client reset, it resets its side with `RequestAborted`,
so a client with an mpsc response gets an error instead of a clean end.
After a remote send fails, later sends get the same error if the receiver
ended the channel, and `Io(BrokenPipe)` if this sender closed it.
The client encoded a request, and the oneshot and mpsc senders encoded a message, each with its own copy of the size check, the encoding, and the reset. A message that passed the size check but then failed to encode gave an `Io` error, and a request in that case reset its stream with `RequestAborted` instead of `RequestEncodeFailed`. `encode` now measures a value once, checks its size, and encodes it, and `encode_message` also resets the stream of a channel message that does not encode.
When a default `Handler` rejects a request, it resets the streams of the request and then closes the connection with the same code. The close arrives first, so the client got an `Io` error, and `remote_code` returned `None`. `remote_code` on the channel errors and on `WriteError` now also returns the irpc code that the peer closed the connection with, and the new `Error::remote_code` returns the code from any of the errors in `Error`. The code mapping impls of the channel errors now live in the channel modules. `From<io::Error>` for the receive errors gives a `Remote` error for a reset with an irpc code, so the receivers use `?`. This also tightens the docs of the error codes and errors, and shortens the tests.
Frando
force-pushed
the
Frando/error-cases-variants
branch
from
October 12, 2026 13:57
2d1f676 to
96f5d23
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This continues the work started in #130 and makes things fully consistent. It properly separates error codes between ones for requests and for channel messages, and exposes the stream resets properly in the corresponding
RecvErrors. It adds new error variants and proper docs around them, stating clearly who causes which kind of failure.Notes and open questions
I'm not super sure if all of them provide much value downstream, but this now fully expresses all variants that we support, and I think it is good to provide consistency in these errors and variants now. If we think it is too much, we can collapse some, but I'd still like to keep the proper error codes. IMO, having these variants doesn't hurt, and to me it feels correct to support all cases properly.
Breaking changes
All these changes only concern you if you match on specific error cases. If not all code continues to work as previously.
rpc::ERROR_CODE_MAX_MESSAGE_SIZE_EXCEEDED,ERROR_CODE_ENCODE_FAILED,ERROR_CODE_DECODE_FAILED, andERROR_CODE_ABORTED. Use the newrpc::ErrorCodeenum withto_codeandfrom_code.SendError::MaxMessageSizeExceededand{mpsc,oneshot}::RecvError::MaxMessageSizeExceededare renamed toMaxSizeExceeded. Each side now gets it only if it found the too large message itself. The other side getsRemote { code: ErrorCode::MessageMaxSizeExceeded }.WriteError::MaxMessageSizeExceededis renamed toMaxSizeExceeded, and the client gets it only if it found the too large request itself.WriteError::Io(which held encode failures) is nowEncodeFailed, andWriteError::Noqis replaced byWriteError::Iowith anio::Error.ReadRequestError::MaxMessageSizeExceededandInvalidRequestare renamed toMaxSizeExceededandMalformed.Remote { code: ErrorCode }onSendError,{mpsc,oneshot}::RecvError, andWriteError, for an irpc error code that the peer reset or stopped the stream with. Before, these cases wereIoerrors.SendError::EncodeFailedand{mpsc,oneshot}::RecvError::DecodeFailed, for a message that this side could not encode or decode. Before, these cases wereIoerrors.remote_code()onSendError,{mpsc,oneshot}::RecvError,WriteError, andirpc::Error. It returns the irpc error code that the peer sent, from aRemoteerror or from the close of the connection.Behavior changes:
Closed, 1RequestAborted, 2RequestMaxSizeExceeded, 3RequestEncodeFailed, 4RequestDecodeFailed, 5MessageMaxSizeExceeded, 6MessageEncodeFailed, 7MessageDecodeFailed. Before, codes 1 to 3 meant too large, encode failed, and decode failed for both requests and channel messages, and code 4 was aborted.RequestMaxSizeExceededorRequestDecodeFailedon both streams and for the connection close. Before, it used code 1 (too large) or code 3 (does not decode).RequestMaxSizeExceededorRequestEncodeFailedinstead ofRequestAborted.RequestAbortedinstead of code 0.Remoteerror converts to anio::ErrorwithConnectionReset, as the reset or stop did before. The other new variants convert withInvalidData. A reset or stop with code 0 stays anIoerror, except that a sender still getsReceiverClosed.Io(BrokenPipe)if this sender closed it, for example after an io error, a message that does not encode or is too large, or a cancelled send.