#[non_exhaustive]pub enum ClientError {
Transport {
command: String,
source: Box<Error>,
},
Cluster {
command: String,
code: i64,
message: String,
raw: String,
},
Http {
command: String,
status: u16,
body: String,
},
Redirected {
command: String,
status: u16,
location: String,
refusal: RedirectRefusal,
heavy: bool,
},
Decode {
command: String,
reason: String,
},
ResponseTooLarge {
command: String,
limit: u64,
},
BatchInterrupted {
answered: Vec<Result<YsonValue>>,
parts: usize,
cause: Box<ClientError>,
},
Io {
path: String,
source: Error,
},
OperationFailed {
id: String,
state: String,
error: Option<String>,
jobs: Vec<JobFailure>,
},
NotAWorker {
path: String,
reason: String,
},
Config(String),
}Expand description
Something went wrong talking to the cluster.
Non-exhaustive. A match over this must carry a _ arm: the ways a
cluster can refuse are the cluster’s to add, not this crate’s to freeze, and
every release so far has added one. Naming a variant, constructing one and
destructuring one all work as before.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Transport
The request could not be made, or the connection failed.
Fields
Cluster
The cluster reported an error.
YTsaurus returns a structured error in the X-YT-Error header; the
message and code are lifted out of it so the common case reads well,
and the whole thing is kept in raw because the nested inner_errors
are often where the real cause is.
Fields
Http
The cluster answered with an unexpected HTTP status and no usable error.
Fields
Redirected
A redirect was refused rather than followed.
A control proxy does not refuse a heavy read: it answers 307 Temporary Redirect naming a data proxy on another host — the
HTTP proxy reference
gives that row as “307 | Redirecting heavy queries from light to heavy
proxies”. Following it without the Authorization header — which is
what ureq does by default — makes the request arrive unauthenticated,
and the cluster then reports Client is missing credentials about a
token that may be perfectly valid. Re-attaching it and going would
follow an instruction the client never asked for, on a request already
addressed elsewhere. This error is the third answer: go nowhere, and say
where the proxy pointed.
The message stops short of declaring the token good. It cannot know that — a gateway in front of the cluster may answer an expired token with a redirect of its own — so it reports the one thing this client is certain of: the credentials never reached the host that answered.
Not every redirect ends here. One that stays on the origin the request
was addressed to is followed, credentials and all, because nothing new
learns the token by it; refusal says which rule this redirect met.
Fields
location: StringWhere it pointed, resolved against the address the request went to,
so a relative Location still names a host. Usually a data proxy on
a different one.
refusal: RedirectRefusalWhich rule the redirect met.
Decode
A response could not be decoded.
Fields
ResponseTooLarge
A buffered response ran past what this client will hold in memory.
Its own variant rather than a ClientError::Decode, which is what it
was first written as. Every other Decode in this crate means the
bytes were read and were not the shape expected — a YSON document that
does not parse, a Skiff frame that ends early, an envelope missing the
key the command answers under. This body was never read at all, and the
difference is the whole of what the caller can do next: a Decode
invites a look at the data, and this invites the streaming half of the
same command, which the message names.
Refused rather than truncated, and never retried — no amount of waiting
shrinks a response, and the host that served it did nothing wrong. That
second half is not this caller’s concern alone: a heavy read blamed on
its host takes a healthy data proxy out of the pool, and enough of them
empty it. See http::body_failure.
limit counts bytes after decompression, which is where they are
actually held — and it is what this client holds, not what the
process needs: the buffer grows by doubling and copies, so peak
residency runs above the number. See http::RESPONSE_LIMIT.
Fields
BatchInterrupted
A split batch stopped part of the way through, and the requests before the failure have already run on the cluster.
Client::execute_batch sends a batch
larger than BatchRequest::with_max_part_size
as several execute_batch requests. There is no rollback: when a later
request fails wholesale, the earlier ones have run and whichever of
their parts succeeded have taken effect. Reporting only the failure
would hide that, and re-running the same
BatchRequest is not a recovery either — a
second execution mints fresh mutation ids, so the parts that already
landed are applied a second time rather than deduplicated.
So the prefix comes back with the failure: answered holds one entry
per part of every request that completed, in part order, with exactly
the per-part Ok/Err split Client::execute_batch
would have handed back. answered.len() is where the batch stopped, and
parts is how many there were, so the parts never attempted are
batch[answered.len()..].
Only for a batch that was split: a batch that fits in one request fails with the underlying error itself, since there is no prefix to report. Put the sequence in a transaction, or keep it inside one request, if a partial application is not something the caller can act on.
The rendered message says the same thing, deliberately. It is the
sentence that reaches a log line and an unwrap() panic, so it must not
draw a line the cluster does not honour: answered.len() is where the
answers stop, not where the effects stop. The request that failed runs
its parts whatever it answers — measured — and answered itself holds
Err entries, which applied nothing at all.
Fields
answered: Vec<Result<YsonValue>>The parts already answered, in part order — every part of every
request that completed, Ok and Err alike.
cause: Box<ClientError>Why the rest never went.
Io
Reading a local file failed.
OperationFailed
An operation finished in a state other than completed.
Fields
jobs: Vec<JobFailure>The jobs that failed, with what they printed.
Empty if the cluster reported none, if job diagnostics are turned
off (see
Client::with_job_diagnostics),
or if asking for them failed — collecting them must never replace
the failure being reported.
NotAWorker
A binary that a cluster node could not run was about to be uploaded.
Fields
Config(String)
The environment did not describe a cluster to talk to.
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
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()