pub struct ConnectError {
pub code: ErrorCode,
pub message: Option<String>,
pub details: Vec<ErrorDetail>,
/* private fields */
}Expand description
A ConnectRPC error.
Fields§
§code: ErrorCodeThe error code.
message: Option<String>Human-readable error message.
details: Vec<ErrorDetail>Additional error details.
Implementations§
Source§impl ConnectError
impl ConnectError
Sourcepub fn new(code: ErrorCode, message: impl Into<String>) -> ConnectError
pub fn new(code: ErrorCode, message: impl Into<String>) -> ConnectError
Create a new error with the given code and message.
Sourcepub fn with_headers(self, headers: HeaderMap) -> ConnectError
pub fn with_headers(self, headers: HeaderMap) -> ConnectError
Add response headers to be included in the error response.
Sourcepub fn with_trailers(self, trailers: HeaderMap) -> ConnectError
pub fn with_trailers(self, trailers: HeaderMap) -> ConnectError
Add response trailers to be included in the error response.
Sourcepub fn response_headers(&self) -> &HeaderMap
pub fn response_headers(&self) -> &HeaderMap
Borrow the response headers. Returns an empty map if none were set.
On an error returned by a client call, these are the headers the
response arrived with. Every terminal error from a
ServerStream carries them, whatever
the protocol and whatever ended the stream.
Sourcepub fn trailers(&self) -> &HeaderMap
pub fn trailers(&self) -> &HeaderMap
Borrow the response trailers. Returns an empty map if none were set.
On an error returned by a client call, these are the trailing
metadata the RPC ended with, populated whenever any was received —
gRPC trailers or a Connect END_STREAM metadata object. The
status-bearing gRPC trailers (grpc-status, grpc-message,
grpc-status-details-bin) are excluded, because their content is
this error’s code, message and
details;
ServerStream::trailers()
reports the wire map verbatim if you need them.
Sourcepub fn response_headers_mut(&mut self) -> &mut HeaderMap
pub fn response_headers_mut(&mut self) -> &mut HeaderMap
Mutably borrow the response headers, allocating an empty map if none were set.
Sourcepub fn trailers_mut(&mut self) -> &mut HeaderMap
pub fn trailers_mut(&mut self) -> &mut HeaderMap
Mutably borrow the response trailers, allocating an empty map if none were set.
Sourcepub fn set_response_headers(&mut self, headers: HeaderMap)
pub fn set_response_headers(&mut self, headers: HeaderMap)
Replace the response headers. An empty map is stored as None.
Sourcepub fn set_trailers(&mut self, trailers: HeaderMap)
pub fn set_trailers(&mut self, trailers: HeaderMap)
Replace the response trailers. An empty map is stored as None.
Sourcepub fn with_http_status(self, status: StatusCode) -> ConnectError
pub fn with_http_status(self, status: StatusCode) -> ConnectError
Set an HTTP status override for this error.
When set, this overrides the default HTTP status derived from the error code. This is useful for HTTP-level errors like 415 Unsupported Media Type.
Sourcepub fn unsupported_media_type(message: impl Into<String>) -> ConnectError
pub fn unsupported_media_type(message: impl Into<String>) -> ConnectError
Create an error for unsupported media type (HTTP 415).
This is used when the client sends a content type that the server doesn’t support.
Sourcepub fn method_not_allowed(message: impl Into<String>) -> ConnectError
pub fn method_not_allowed(message: impl Into<String>) -> ConnectError
Create an error for method not allowed (HTTP 405).
This is used when the client uses an HTTP method other than POST.
Sourcepub fn canceled(message: impl Into<String>) -> ConnectError
pub fn canceled(message: impl Into<String>) -> ConnectError
Create a canceled error.
Sourcepub fn unknown(message: impl Into<String>) -> ConnectError
pub fn unknown(message: impl Into<String>) -> ConnectError
Create an unknown error.
Sourcepub fn invalid_argument(message: impl Into<String>) -> ConnectError
pub fn invalid_argument(message: impl Into<String>) -> ConnectError
Create an invalid argument error.
Sourcepub fn deadline_exceeded(message: impl Into<String>) -> ConnectError
pub fn deadline_exceeded(message: impl Into<String>) -> ConnectError
Create a deadline exceeded error.
Sourcepub fn not_found(message: impl Into<String>) -> ConnectError
pub fn not_found(message: impl Into<String>) -> ConnectError
Create a not found error.
Sourcepub fn already_exists(message: impl Into<String>) -> ConnectError
pub fn already_exists(message: impl Into<String>) -> ConnectError
Create an already exists error.
Sourcepub fn permission_denied(message: impl Into<String>) -> ConnectError
pub fn permission_denied(message: impl Into<String>) -> ConnectError
Create a permission denied error.
Sourcepub fn resource_exhausted(message: impl Into<String>) -> ConnectError
pub fn resource_exhausted(message: impl Into<String>) -> ConnectError
Create a resource exhausted error.
Sourcepub fn failed_precondition(message: impl Into<String>) -> ConnectError
pub fn failed_precondition(message: impl Into<String>) -> ConnectError
Create a failed precondition error.
Sourcepub fn aborted(message: impl Into<String>) -> ConnectError
pub fn aborted(message: impl Into<String>) -> ConnectError
Create an aborted error.
Sourcepub fn out_of_range(message: impl Into<String>) -> ConnectError
pub fn out_of_range(message: impl Into<String>) -> ConnectError
Create an out of range error.
Sourcepub fn unimplemented(message: impl Into<String>) -> ConnectError
pub fn unimplemented(message: impl Into<String>) -> ConnectError
Create an unimplemented error.
Sourcepub fn internal(message: impl Into<String>) -> ConnectError
pub fn internal(message: impl Into<String>) -> ConnectError
Create an internal error.
Create an unavailable error.
Sourcepub fn data_loss(message: impl Into<String>) -> ConnectError
pub fn data_loss(message: impl Into<String>) -> ConnectError
Create a data loss error.
Sourcepub fn unauthenticated(message: impl Into<String>) -> ConnectError
pub fn unauthenticated(message: impl Into<String>) -> ConnectError
Create an unauthenticated error.
Sourcepub fn with_detail(self, detail: ErrorDetail) -> ConnectError
pub fn with_detail(self, detail: ErrorDetail) -> ConnectError
Add an error detail.
Sourcepub fn with_source(
self,
source: impl Into<Box<dyn Error + Send + Sync>>,
) -> ConnectError
pub fn with_source( self, source: impl Into<Box<dyn Error + Send + Sync>>, ) -> ConnectError
Attach the underlying cause, surfaced through
Error::source.
Unlike message (which is sent over the wire and shown to callers),
the source is local-only — useful for logging/observability without
leaking internal detail to the client. It is never populated by
decoding a ConnectError received over the wire (there is nothing to
attach), only by local code that calls this method — so source()
on an error a client parsed from a server response is always None.
Accepts either a concrete error or an already-boxed one, so it
composes with transport errors that are type-erased before reaching
this call. (The same conversion also accepts a bare String or
&str, which becomes a source with no type to downcast to — pass a
real error type.) Replaces any source attached by a previous call.
This does not touch message. The crate’s own transport errors put
the cause’s Display text in message and attach it here, so plain
{} formatting stays informative; a renderer that also walks the
source chain will show that text twice.
Attach a cause already held as a SharedSource — typically one taken
from another ConnectError with source_arc when
rebuilding an error under a different code. Passing such a handle to
with_source instead would compile but wrap it in
a second Arc link that hides the concrete type from downcast_ref.
Sourcepub fn source_arc(&self) -> Option<Arc<dyn Error + Send + Sync>>
pub fn source_arc(&self) -> Option<Arc<dyn Error + Send + Sync>>
The underlying cause as a shared handle, for carrying it into another
error type. Error::source returns the
same error by reference when it only needs inspecting.
use connectrpc::{ConnectError, SharedSource};
#[derive(Debug, thiserror::Error)]
enum FetchError {
#[error("profile service unreachable")]
Unreachable(#[source] SharedSource),
#[error(transparent)]
Rpc(ConnectError),
}
fn classify(err: ConnectError) -> FetchError {
match err.source_arc() {
Some(cause) => FetchError::Unreachable(cause),
None => FetchError::Rpc(err),
}
}
let refused = std::io::Error::from(std::io::ErrorKind::ConnectionRefused);
let e = classify(ConnectError::unavailable("connect failed").with_source(refused));
let FetchError::Unreachable(cause) = &e else { panic!() };
// Downcast the handle itself; see `SharedSource` for why the outer
// error's `source()` chain shows an `Arc` link here instead.
let io = cause.downcast_ref::<std::io::Error>().unwrap();
assert_eq!(io.kind(), std::io::ErrorKind::ConnectionRefused);Build an unavailable error from a raw client transport failure,
keeping the failure both in message (as "{context}: {err}") and as
the source.
This is the convention the built-in transports follow for the
failures they classify themselves; a custom
ClientTransport can use it to
match them. Pass the underlying transport error, not a ConnectError:
the result is always unavailable, so wrapping an already-classified
error here would bury its code — return that error directly instead.
(Contrast the From<std::io::Error> impl, which is for handler-side
I/O and yields internal.)
Sourcepub fn http_status(&self) -> StatusCode
pub fn http_status(&self) -> StatusCode
Get the HTTP status code for this error.
Returns the HTTP status override if set, otherwise derives it from the error code.
Source§impl ConnectError
impl ConnectError
Sourcepub fn into_http_response(
self,
request_headers: &HeaderMap,
) -> Response<ConnectRpcBody>
pub fn into_http_response( self, request_headers: &HeaderMap, ) -> Response<ConnectRpcBody>
Render this error as a complete HTTP response in the wire format matching the inbound request’s protocol.
This is the building block for tower::Layers that short-circuit a
request (auth, rate limiting, validation) before it reaches
ConnectRpcService. A layer cannot reuse the service’s internal error
rendering, but still needs to produce a response that the calling
client will decode as a structured error rather than a transport
failure. Each protocol expects a different wire shape:
- Connect unary (
application/proto,application/json, or absent — Connect GET requests carry no request body orContent-Type): a non-200 HTTP status with a JSON error body. Connect unary error bodies are spec-required JSON regardless of the request codec. - Connect streaming (
application/connect+{proto,json}): HTTP 200 with the error in anEndStreamResponseenvelope. - gRPC / gRPC-Web (
application/grpc*): HTTP 200 withgrpc-statusandgrpc-messagetrailers (as HTTP/2 trailers for gRPC, encoded in the body for gRPC-Web).
The protocol is detected from request_headers via
Protocol::detect. When detection fails — an unrecognized
Content-Type, or none at all — the Connect unary JSON shape is used,
which is the most universally parseable fallback.
gRPC and gRPC-Web use the same framed wire shape for unary and streaming calls, so the trailers-only response is always correct regardless of the method’s cardinality.
§Example
use connectrpc::ConnectError;
// Inside a tower::Service::call wrapping ConnectRpcService:
fn call(&mut self, req: http::Request<B>) -> Self::Future {
if !self.is_authorized(&req) {
let resp = ConnectError::permission_denied("access denied")
.into_http_response(req.headers());
return Box::pin(std::future::ready(Ok(resp)));
}
// ... call inner service ...
}Trait Implementations§
Source§impl Clone for ConnectError
impl Clone for ConnectError
Source§fn clone(&self) -> ConnectError
fn clone(&self) -> ConnectError
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ConnectError
impl Debug for ConnectError
Source§impl<'de> Deserialize<'de> for ConnectError
impl<'de> Deserialize<'de> for ConnectError
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<ConnectError, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<ConnectError, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Display for ConnectError
impl Display for ConnectError
Source§impl Error for ConnectError
impl Error for ConnectError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<Error> for ConnectError
impl From<Error> for ConnectError
Source§fn from(err: Error) -> ConnectError
fn from(err: Error) -> ConnectError
Source§impl From<Error> for ConnectError
Lets Response::try_with_header(..)? propagate naturally inside a
handler.
impl From<Error> for ConnectError
Lets Response::try_with_header(..)? propagate naturally inside a
handler.
Source§fn from(err: Error) -> ConnectError
fn from(err: Error) -> ConnectError
Source§impl IntoResponse for ConnectError
impl IntoResponse for ConnectError
Source§fn into_response(self) -> Response<Body>
fn into_response(self) -> Response<Body>
Source§impl Serialize for ConnectError
impl Serialize for ConnectError
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl !RefUnwindSafe for ConnectError
impl !UnwindSafe for ConnectError
impl Freeze for ConnectError
impl Send for ConnectError
impl Sync for ConnectError
impl Unpin for ConnectError
impl UnsafeUnpin for ConnectError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T, S> Handler<IntoResponseHandler, S> for T
impl<T, S> Handler<IntoResponseHandler, S> for T
Source§fn call(
self,
_req: Request<Body>,
_state: S,
) -> <T as Handler<IntoResponseHandler, S>>::Future
fn call( self, _req: Request<Body>, _state: S, ) -> <T as Handler<IntoResponseHandler, S>>::Future
Source§fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>where
L: Layer<HandlerService<Self, T, S>> + Clone,
<L as Layer<HandlerService<Self, T, S>>>::Service: Service<Request<Body>>,
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>where
L: Layer<HandlerService<Self, T, S>> + Clone,
<L as Layer<HandlerService<Self, T, S>>>::Service: Service<Request<Body>>,
tower::Layer to the handler. Read moreSource§fn with_state(self, state: S) -> HandlerService<Self, T, S>
fn with_state(self, state: S) -> HandlerService<Self, T, S>
Service by providing the stateSource§impl<H, T> HandlerWithoutStateExt<T> for H
impl<H, T> HandlerWithoutStateExt<T> for H
Source§fn into_service(self) -> HandlerService<H, T, ()>
fn into_service(self) -> HandlerService<H, T, ()>
Service and no state.Source§fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
MakeService and no state. Read more