pub enum Error {
Show 21 variants
PktLine(Error),
Io(Error),
Store(Error),
Pack(String),
ObjectMissing {
oid: ObjectId,
context: Option<String>,
},
CorruptObject {
oid: ObjectId,
reason: String,
},
Protocol(String),
OverCeiling(String),
Refused(String),
ObjectFormatMismatch {
ours: &'static str,
theirs: String,
},
RemoteObjectFormat {
ours: &'static str,
theirs: String,
},
Remote(String),
UnknownArgument {
command: &'static str,
argument: String,
},
UnsupportedFilter {
spec: String,
reason: &'static str,
},
WantNotAdvertised {
oid: ObjectId,
},
UnexpectedEof(&'static str),
WalkBudget {
limit: usize,
},
WalkTooLarge {
held: usize,
limit: usize,
},
WalkPoolFull {
wanted: usize,
in_flight: usize,
limit: usize,
},
RequestTooLarge {
limit: usize,
what: &'static str,
},
ObjectTooLarge {
oid: ObjectId,
size: u64,
limit: u64,
},
}Expand description
Everything gunnar-wire can fail with.
Variants§
PktLine(Error)
The framing layer rejected a line.
Io(Error)
The transport failed.
Store(Error)
The storage layer failed.
Pack(String)
Writing or indexing a packfile failed.
A message, not another crate’s error type. It was
#[from] gunnar_pack::Error until 2026-08-10, and that one #[from]
was the last thing making gunnar-pack — and behind it gix-pack and
ten more gix crates — a normal dependency of a crate that has not called
a pack writer or a pack indexer since the engine seam landed. See
crate::pack. Nothing under src/ constructs this; a packfile is
somebody else’s to write, and the somebody is an engine behind the
contract.
ObjectMissing
An object the protocol requires is not in the repository.
On the serving side this means a corrupt repository; on the receiving side it means a push whose connectivity does not close.
Fields
CorruptObject
An object could not be parsed as the kind it claims to be.
Protocol(String)
The peer sent something the protocol does not allow here.
OverCeiling(String)
A fetch’s packfile passed the byte ceiling it was held to
(FetchPack::with_ceiling)
and was cut mid-transfer; the ingest was handed at most the ceiling and
one byte, and nothing was stored. The text is the ceiling’s own refusal,
verbatim — the sentence whoever set it composed, the same one a push past
the same ceiling is told — never “the pack is corrupt”, which is what the
indexer would have made of the cut stream.
Refused(String)
A policy refused the pushed pack before any of it was kept — the
encrypted-repository gate, run on the pack in quarantine (gunnar-server
encrypted_quarantine). Its sentence is the client’s, word for word:
it names the file and the fix, and it reveals nothing the pusher did
not send.
ObjectFormatMismatch
The peer named a hash algorithm this repository does not use.
Getting this wrong silently is the documented, session-costing bug of Object-format negotiation: a sha1 answer to a sha256 repository produces an empty response rather than an error, so it is made loud here.
Fields
RemoteObjectFormat
The same mismatch as Error::ObjectFormatMismatch, from the client’s
chair.
Two variants and not one because the sentence is the point. The other says “the client asked for X, but this repository is Y”, which is what a server tells a client; an operator reading that about their own mirror would go looking for a client that does not exist. This one names the remote as the remote.
The failure it prevents is object-format negotiation’s, unchanged: a sha1 client against a
sha256 remote does not error, it negotiates an empty answer, so
fetch_pack refuses at the advertisement rather than reporting a
successful fetch of nothing.
Remote(String)
The remote reported a fatal condition on sideband 3.
Verbatim, because it is the only thing the remote will ever say about
why: band 3 is how upload-pack reports “repository not found” or
“want is not a valid object” once a sideband is open, and a client that
turned it into “the transfer failed” would throw away the whole
diagnosis.
UnknownArgument
An argument that is not in this command’s argument table.
Fields
UnsupportedFilter
A filter specification gunnar does not implement.
WantNotAdvertised
A want naming something that is not an advertised reference tip.
Serving arbitrary object ids leaks objects that are not reachable from any reference, which is how “deleted” branches stay fetchable.
UnexpectedEof(&'static str)
The peer hung up in the middle of a message.
WalkBudget
A traversal ran past its object budget.
A budget rather than an unbounded walk because the object graph comes from the network: a crafted repository must not be able to make the server allocate without limit.
WalkTooLarge
A traversal would have held more object bookkeeping than
Limits::walk_bytes allows.
The bytes are the ids the walk is holding live, charged at
WALK_BYTES_PER_OBJECT, which is a
measured rate and not a struct size. Nothing is inflated to arrive at it:
charging a walk by decompressing what it walks over is the defect that
cost gix-odb half its read-side CPU.
WalkPoolFull
The server-wide WalkPool had no room left.
Not the same refusal as Error::WalkTooLarge, and telling them apart
is the point: this one says the request was reasonable and the machine
is full, so a client that waits and retries will get served. The other
says this request will never fit.
Fields
RequestTooLarge
The peer’s request would have cost more memory than
Limits::request_bytes allows.
The budget is spent as the request is framed, so this is raised with
the ceiling’s worth of bytes held and not a byte more. A client that
sends have lines forever is refused here rather than at the point where
the allocator gives up.
Fields
ObjectTooLarge
An object is larger than Limits::object_bytes
allows gunnar to materialise while serving a fetch.
Read from the object’s header, before its content, so the ceiling refuses the transfer rather than reporting on an allocation that has already happened. Refused rather than skipped: a pack missing an object its trees name is a corrupt clone, which is worse than no clone.
Implementations§
Source§impl Error
impl Error
Sourcepub fn pack(what: impl Display) -> Self
pub fn pack(what: impl Display) -> Self
A packfile could not be written or indexed.
pub rather than pub(crate) because the only callers are outside this
crate: a PackIngest is
caller-supplied, so whoever indexes the pack is also whoever names why
it would not index. See Error::Pack.
Sourcepub fn client_message(&self) -> String
pub fn client_message(&self) -> String
The one-line text this error is worth sending to a client, without leaking server paths or internals.
§Why this is not to_string()
It was, and the doc comment above it made the claim anyway. Variants of
this enum are #[error(transparent)] over another crate’s error —
Error::Io and Error::Store, and until 2026-08-10
Error::Pack as well — so whatever the storage layer said went out
verbatim. gunnar_store::Error::StoreLocked
renders the absolute path of the lock file, and
crate::receive_pack puts client_message() straight into the
unpack line of a push report, so git push printed a server path to
whoever pushed. gunnar-ssh and gunnar-lfs both redact at this seam
already (DispatchError::client_message, gunnar_lfs::Error::client_message);
this crate was the one that did not.
Everything else stays verbatim, and that is deliberate: an oid, a
filter spec, an argument name and a byte ceiling are either the
client’s own words or facts about the protocol, and they are what makes
a refusal actionable without a server login. git’s own upload-pack
tells a client which object it wanted and could not have.
The unredacted text is still what the server logs — see
git.upload_pack.failed, which carries %err and not this.
Trait Implementations§
Source§impl Error for Error
impl Error for Error
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()