pub enum RepairError {
Backend {
op: &'static str,
bucket: String,
key: String,
cause: String,
},
FrameScan {
bucket: String,
key: String,
cause: String,
},
BodyTooLarge {
size: u64,
cap: u64,
},
MissingContentLength {
bucket: String,
key: String,
},
OverwrittenDuringRepair {
bucket: String,
key: String,
head_etag: String,
},
SidecarTooLarge {
bucket: String,
key: String,
size: u64,
cap: u64,
},
NotFramed {
bucket: String,
key: String,
},
EncryptedSidecarUnsupported {
bucket: String,
key: String,
message: String,
},
SseDecryptFailed {
bucket: String,
key: String,
cause: String,
},
}Variants§
Backend
FrameScan
BodyTooLarge
MissingContentLength
HEAD on {bucket}/{key} returned no Content-Length header. The
body-size cap that prevents OOM on a runaway repair relies on this
being available, so the tool fails closed rather than treating a
missing length as zero (which would silently bypass the cap).
OverwrittenDuringRepair
If-Match race detector: the object was overwritten between the
initial HEAD (whose ETag we stamped into the sidecar) and the GET.
Returned by repair_sidecar so the operator can re-run instead of
writing a sidecar that’s immediately stale.
SidecarTooLarge
v0.9 #106-audit-R5 P2-R5 (Codex): the <key>.s4index body
the backend reports exceeds MAX_SIDECAR_BODY_BYTES, which
exceeds the codec spec’s max legitimate sidecar (~512 MiB).
Surfaced before the GET to avoid loading a multi-GiB corrupt
or attacker-supplied .s4index blob into the operator’s
repair process (DoS hardening). Operators with anomalously
large legitimate sidecars (multi-million-frame objects) can
raise the cap by changing the constant — but the practical
answer is “treat the underlying object as not-sidecared
(the GET path already falls back to a full read in that
case)” rather than chasing larger sidecars.
NotFramed
v0.9 #106-audit-R3 P2-R3: the object body has no S4F2 frame
magic — it’s a passthrough / raw-bytes object the server
intentionally never sidecared (service.rs::put_object only
builds a sidecar when is_framed && !will_encrypt). Writing
an empty <key>.s4index would silently break Range GET:
FrameIndex::lookup_range over zero entries returns None,
the GET path falls into the “invalid range” branch instead of
the correct passthrough-range fallback that exists for
sidecar-less objects. Surface as a typed error so the
operator knows the object isn’t a candidate for sidecar
repair (and verify-sidecar will already classify it as
MissingHarmless with frame_count=0).
EncryptedSidecarUnsupported
v0.9 #106-audit-R2 P2-INT-1 (introduced) / v0.10 #A1 (refined):
the object body the backend returned is an SSE-S4 encrypted
envelope (S4E1/S4E2/S4E3/S4E4/S4E5/S4E6) and the
repair tool either was not given a matching keyring or the
envelope is not the chunked S4E6 variant the repair tool can
rebuild from.
repair_sidecar runs against the BACKEND (not the gateway), so
the body it sees is ciphertext — feeding that to the frame
scanner would surface as a confusing FrameScan because the
S4F2 frame magic is hidden inside the encrypted payload. With a
keyring + the chunked S4E6 envelope, the new
repair_sidecar_with_keyring path decrypts in-process and
stamps a v3 sidecar carrying the SSE binding (key_id / salt /
chunk_size / chunk_count / plaintext_len / header_bytes); the
non-S4E6 envelopes (S4E1/E2/E3/E4/E5) are intentionally out of
scope (buffered AEAD frames have no per-chunk geometry, and
SSE-C / SSE-KMS need different key-material plumbing) — they
surface here so the operator routes those repairs through a
server-mode rebuild path or re-PUT.
SseDecryptFailed
v0.10 #A1: a keyring WAS supplied for an SSE-S4 chunked (S4E6)
object, but parsing the envelope header or decrypting one of
the AES-GCM chunks failed. The most common cause is a key
mismatch: the operator’s --sse-s4-key is not the slot the
object was encrypted under at PUT time. Other causes are
envelope truncation / tampering (chunk auth-tag verify fails).
Surfaced as a distinct variant from EncryptedSidecarUnsupported
so the CLI can give operator-actionable guidance (“check your
--sse-s4-key-rotated list against the PUT-time slot”) instead
of the unsupported-envelope hint.
Trait Implementations§
Source§impl Debug for RepairError
impl Debug for RepairError
Source§impl Display for RepairError
impl Display for RepairError
Source§impl Error for RepairError
impl Error for RepairError
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 Freeze for RepairError
impl RefUnwindSafe for RepairError
impl Send for RepairError
impl Sync for RepairError
impl Unpin for RepairError
impl UnsafeUnpin for RepairError
impl UnwindSafe for RepairError
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more