#[non_exhaustive]pub enum ClientError {
Show 15 variants
Http(HttpError),
InvalidHeaderValue(InvalidHeaderValueError),
AuthFailed(u16),
Parse(ParseError),
BlobIntegrityMismatch {
expected: String,
actual: String,
},
InvalidArgument(String),
InvalidSession(String),
MethodNotFound(String),
MethodError {
error_type: String,
description: Option<String>,
},
Serialize(SerializeError),
SseFrameTooLarge {
limit: usize,
},
ResponseTooLarge {
actual: u64,
limit: u64,
},
WebSocket(WebSocketError),
UnexpectedResponse(String),
RateLimited {
retry_after: UTCDate,
},
}Expand description
Errors produced by the base JMAP client.
Variants cover transport failures (Http, WebSocket), authentication
(AuthFailed), JMAP protocol errors (MethodError, UnexpectedResponse),
caller bugs (InvalidArgument, InvalidHeaderValue, Serialize), and
resource-exhaustion guards (ResponseTooLarge, SseFrameTooLarge).
Marked #[non_exhaustive] so additional variants may be introduced in
minor releases. See per-variant documentation for retriability guidance.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Http(HttpError)
Network or TLS error from the HTTP layer. May be retriable (transient network failure) or permanent (TLS configuration error). Indicates a network or transport problem, not a JMAP protocol error.
The payload is an opaque HttpError that does not expose any
third-party error type — this crate’s HTTP transport can be swapped
or its major version bumped without affecting downstream callers.
Use HttpError::is_timeout, HttpError::status, etc. to diagnose.
InvalidHeaderValue(InvalidHeaderValueError)
A header value could not be encoded. Indicates a caller bug — the credential string contains characters that are not valid HTTP header value characters. Not retriable.
AuthFailed(u16)
The server returned HTTP 401 (authentication failure) or 403 (authorization failure — credentials present but insufficient). Not retriable without correcting credentials.
Parse(ParseError)
A server response could not be parsed or did not match the expected shape. Indicates the server sent a malformed response. Not retriable without a server fix.
The payload is an opaque ParseError that does not expose the
underlying JSON parser’s error type — the variant is insulated from
a future parser swap. Construct explicitly:
.map_err(ClientError::from_parse) (or
.map_err(jmap_base_client::ClientError::from_parse) from outside
the crate). Pattern-match via ClientError::Parse(e) => e.line(),
e.column(), e.classify() — see ParseError.
BlobIntegrityMismatch
Blob SHA-256 mismatch on upload or download. Indicates in-transit corruption or a misbehaving server. Not retriable without re-fetching metadata.
§Field semantics across both call sites (bd:JMAP-6r7c.10)
The same variant is emitted from both upload and download paths and the role of each field is constant across paths:
expectedis the pre-stated digest the client was comparing against — i.e. the value that should hold if the bytes are intact.actualis the freshly-observed digest the client just computed or just learned.
The source of each value depends on which call produced the error:
| Call site | expected | actual |
|---|---|---|
JmapClient::upload_blob | client’s own SHA-256 of the bytes about to be uploaded | server’s reported SHA-256 in the upload response |
JmapClient::download_blob | DownloadBlobParams::expected_sha256 supplied by the caller (typed jmap_cid_types::Sha256, guaranteed canonical lowercase) | client’s SHA-256 of the actually-received bytes |
Both digests are canonical 64-character lowercase hex (per draft-atwood-jmap-cid-00 §2 ABNF).
Fields
expected: StringPre-stated SHA-256 hex digest the client was comparing against.
On upload, this is the client’s own pre-upload computation; on
download, this is the caller-supplied
DownloadBlobParams::expected_sha256
(typed jmap_cid_types::Sha256, guaranteed canonical lowercase).
InvalidArgument(String)
A caller-supplied argument violates a precondition (e.g. empty token, colon in BasicAuth username, missing required filter field).
InvalidSession(String)
The JMAP Session object from the server was missing a required field. Indicates a server-side bug or incompatible server. Not retriable.
MethodNotFound(String)
The JMAP API response did not contain the expected method call ID. Indicates a server-side bug or unexpected response shape.
MethodError
The JMAP server returned a method-level error object (RFC 8620 §3.6).
Retriability depends on error_type (e.g. serverFail may be
retried; invalidArguments is not retriable).
description is None when the server omits the optional description field.
Fields
Serialize(SerializeError)
A JMAP request could not be serialized to JSON when sending over WebSocket. Indicates a caller bug — the data structure contains non-serializable values. Not retriable.
This error is only returned by WsSession::send_request; the HTTP
call() path delegates serialization to reqwest, which surfaces
serialization failures as ClientError::Http.
The payload is an opaque SerializeError that does not expose the
underlying JSON serializer’s error type. Construct explicitly:
.map_err(ClientError::from_serialize). Pattern-match via
ClientError::Serialize(e) => e.line(), e.column(), e.classify()
— see SerializeError.
SseFrameTooLarge
An SSE frame exceeded the configured buffer limit
(ClientConfig::max_sse_frame). The stream is terminated after this
error. Indicates a misbehaving or hostile server.
ResponseTooLarge
A server response body exceeded the enforced size limit. Protects
against unbounded memory allocation from malicious or buggy servers.
actual is in bytes (from Content-Length or actual read size).
Fields
WebSocket(WebSocketError)
A WebSocket transport error (connection, framing, or TLS). May be retriable (transient network failure) or permanent (TLS config error).
The payload is an opaque WebSocketError that does not expose any
third-party error type — see HttpError for the same SemVer
rationale. Use WebSocketError::is_io,
WebSocketError::is_protocol, etc. to diagnose.
UnexpectedResponse(String)
The server returned a response that violates the JMAP protocol (outside
the Session fetch path). Examples: wrong Content-Type on an SSE
connection, unexpected response shape on a non-session endpoint.
Distinct from ClientError::InvalidSession, which indicates a
problem with the Session document itself. Not retriable without a
server fix.
RateLimited
Server rate-limited the request. retry_after indicates when to retry.
§⚠ Not currently produced by this crate (bd:JMAP-6lsm.3, bd:JMAP-6r7c.33)
HTTP 429 responses fall through reqwest::error_for_status() and
surface as ClientError::Http today, NOT as ClientError::RateLimited.
A caller that matches only on this variant will miss every actual
429 from the base crate. Until bd:JMAP-6lsm.3 lands the native
429 → RateLimited conversion, callers MUST handle both cases:
match err {
ClientError::RateLimited { retry_after } => {
// Eventually the only path; today only produced by extension
// crates that wrap this crate's error conversion.
sleep_until(retry_after).await;
}
ClientError::Http(http) if http.status() == Some(429) => {
// Base-crate path today (bd:JMAP-6lsm.3 will collapse this
// into the RateLimited arm above).
sleep(Duration::from_secs(30)).await; // or parse Retry-After
}
other => { /* propagate */ }
}§Why the variant ships anyway
The variant is part of the public contract so:
- Extension crates that wrap or replace this crate’s transport may
detect 429 + parse
Retry-Afterthemselves and produceRateLimitedfrom their own error-conversion code. - Callers that want to handle rate limiting via this typed variant
have a stable target to match on, even before the conversion
logic lands here (tracked under
bd:JMAP-6lsm.3).
The variant shape will not change in a backward-incompatible way
when 429 → RateLimited conversion lands — it is part of a
#[non_exhaustive] enum and the struct payload is itself stable,
so callers writing the dual-match pattern above today will not
need to adjust when the migration completes.
Implementations§
Source§impl ClientError
impl ClientError
Sourcepub fn from_parse(e: Error) -> ClientError
pub fn from_parse(e: Error) -> ClientError
Convert a serde_json::Error from a deserialize / parse step
into a ClientError::Parse variant carrying an opaque
ParseError payload (bd:JMAP-6r7c.26).
Public because extension client crates (jmap-mail-client,
jmap-chat-client, etc.) need to surface their own JSON parse
failures as ClientError::Parse. Use in .map_err:
let val: T = serde_json::from_slice(&bytes)
.map_err(jmap_base_client::ClientError::from_parse)?;A future JSON-parser swap would deprecate this constructor in
favor of an analogous one for the new parser; the variant
payload type (ParseError) stays stable.
Sourcepub fn from_serialize(e: Error) -> ClientError
pub fn from_serialize(e: Error) -> ClientError
Convert a serde_json::Error from a serialize step into a
ClientError::Serialize variant carrying an opaque
SerializeError payload (bd:JMAP-6r7c.26).
Public for the same reason as from_parse.
Trait Implementations§
Source§impl Debug for ClientError
impl Debug for ClientError
Source§impl Display for ClientError
impl Display for ClientError
Source§impl Error for ClientError
impl Error for ClientError
1.30.0 · 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()
Auto Trait Implementations§
impl !RefUnwindSafe for ClientError
impl !UnwindSafe for ClientError
impl Freeze for ClientError
impl Send for ClientError
impl Sync for ClientError
impl Unpin for ClientError
impl UnsafeUnpin for ClientError
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> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.