#[non_exhaustive]pub enum StreamError {
Show 17 variants
Transport(Box<Status>),
Connect(Error),
InvalidEndpoint(String),
InvalidToken,
InsecureCredential(String),
Unauthenticated(Box<Status>),
PermissionDenied(Box<Status>),
QuotaExhausted(Box<Status>),
RateLimited {
retry_after: Option<Duration>,
},
ReplayUnavailable,
PrefixBitsOutOfRange {
got: u32,
min: u32,
max: u32,
},
InvalidArgument(String),
Decode(String),
ControlClosed,
WatchSetLoader(Box<dyn Error + Send + Sync>),
NodeTooOld {
node: String,
sdk: &'static str,
},
SchemaMismatch {
node: u32,
sdk: u32,
},
}Expand description
An error from the streaming client.
Lagged is deliberately not here — a slow-consumer lag notice is a
normal Event, recoverable and carrying a resume cursor.
Variants here are conditions that stop forward progress on a call.
The variants that wrap a tonic::Status keep it boxed so the server’s
message and details survive classification; use is_retryable
to decide whether to back off and retry versus give up.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Transport(Box<Status>)
An unclassified transport or RPC status from the server.
Connect(Error)
Failed to establish the underlying transport channel.
InvalidEndpoint(String)
The endpoint string could not be parsed.
InvalidToken
The supplied bearer token is not a valid HTTP header value.
InsecureCredential(String)
A bearer token was configured against an endpoint that is not encrypted, so the token — and, on a scan-key watch, the BIP 352 scan secrets that share the stream — would cross the network in cleartext.
Use an https:// endpoint with tls
or tls_ca_pem. For loopback
or a test harness, name the risk with
insecure_bearer_token.
Unauthenticated(Box<Status>)
The bearer token was missing, malformed, or rejected (gRPC
UNAUTHENTICATED). Potentially fixable by presenting a valid token.
PermissionDenied(Box<Status>)
The principal is authenticated but lacks the required capability
(stream:subscribe to open, stream:watch to add watches) — gRPC
PERMISSION_DENIED. A permanent configuration error, not retryable.
QuotaExhausted(Box<Status>)
The server’s subscription cap or a per-principal rate limit was hit when
the stream was opened (gRPC RESOURCE_EXHAUSTED). Both are transient:
back off and retry. A full watch quota never surfaces here; a refused
add arrives as Event::WatchAddRejected.
RateLimited
Reserved for explicit rate-limit signaling in the resilience layer; not
produced yet. The server answers an over-rate SetCursor re-anchor
in-band, as Event::CursorRejected with
CursorRejectReason::RateLimited,
not with a status.
Reserved. from_cursor replay against a server with no block source is a
silent server-side fallback to forward-only (no status), so this is not
produced from the wire yet; the resilience layer detects the degraded
case from the event stream.
PrefixBitsOutOfRange
A prefix watch was rejected because bits is outside the server’s
configured [streamprefixminbits, streamprefixmaxbits] range.
InvalidArgument(String)
A client-side argument was rejected before reaching the wire (e.g. a
prefix whose byte length does not match its bits).
Decode(String)
A received message could not be decoded into a typed value.
ControlClosed
The control channel was closed before the message could be sent (the watch stream has been torn down).
WatchSetLoader(Box<dyn Error + Send + Sync>)
A user-supplied watch-set loader (see
ResilientWatchConfig::watch_set_loader)
returned an error while rebuilding the watch-set on (re)connect. Treated
by ResilientWatch as a transient
reconnect-level condition: the loader is retried after a backoff on the
next connect rather than surfaced, so a momentary failure of the
integrator’s source-of-truth does not crash the consumer.
NodeTooOld
The node is two or more minor versions (or a major version) older than
this SDK. Features the SDK was built against may be missing and request
fields the node does not recognise would be silently ignored, so the
stream is refused. Upgrade the node, or accept the risk with
allow_old_node, which turns
this into a logged warning. Not retryable.
Fields
SchemaMismatch
The node speaks a different event schema version than this SDK. Always
refused, whatever the versions; allow_old_node does not apply. Not
retryable.
Implementations§
Source§impl StreamError
impl StreamError
Sourcepub fn is_retryable(&self) -> bool
pub fn is_retryable(&self) -> bool
Whether retrying the operation (after a backoff) could plausibly succeed.
true for transport failures the gRPC layer marks transient
(UNAVAILABLE, DEADLINE_EXCEEDED, ABORTED, CANCELLED,
RESOURCE_EXHAUSTED), for connection failures, and for the reserved
RateLimited. false for permanent conditions — bad endpoint/token,
PERMISSION_DENIED, client-side argument errors. Unauthenticated is
reported non-retryable: a blind retry with the same token will not help;
the caller should re-auth and reconnect deliberately. NodeTooOld and
SchemaMismatch are non-retryable: reconnecting to the same node gives
the same answer.
Trait Implementations§
Source§impl Debug for StreamError
impl Debug for StreamError
Source§impl Display for StreamError
impl Display for StreamError
Source§impl Error for StreamError
impl Error for StreamError
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 StreamError
impl From<Error> for StreamError
Auto Trait Implementations§
impl !RefUnwindSafe for StreamError
impl !UnwindSafe for StreamError
impl Freeze for StreamError
impl Send for StreamError
impl Sync for StreamError
impl Unpin for StreamError
impl UnsafeUnpin for StreamError
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> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request