pub enum PackageError {
Show 19 variants
UnsupportedHost(UnsupportedHost),
NoPackagePublished {
os: Os,
arch: Arch,
},
ChecksumAbsent {
version: RunnerVersion,
os: Os,
arch: Arch,
published: PublishedChecksum,
},
ChecksumMismatch {
version: RunnerVersion,
expected: Sha256Hex,
actual: Sha256Hex,
},
MalformedDigest {
raw: String,
},
VersionRejected {
version: Option<RunnerVersion>,
detail: Option<String>,
},
CatalogUnavailable {
detail: String,
},
Download {
detail: String,
},
UnrecognisedVersion {
raw: String,
},
UnsupportedArchive {
filename: String,
},
UnsafeArchiveEntry {
entry: String,
},
Extract {
detail: String,
},
VersionInUse {
version: RunnerVersion,
attempt: AttemptId,
state: AttemptState,
},
VersionHeldByUnknownAttempt {
version: RunnerVersion,
attempt: AttemptId,
},
UnreadableLease {
path: PathBuf,
},
WorkspaceInsideCache {
attempt: AttemptId,
path: PathBuf,
},
NotInstalled {
version: RunnerVersion,
},
Io {
what: &'static str,
path: PathBuf,
source: Error,
},
Exhausted {
attempts: u32,
source: Box<PackageError>,
},
}Expand description
Everything that can stop a package reaching the cache.
§Terminal versus retryable is not a style choice here
03-control-flows.md flow 2 fixes the split, and it is narrower than it
looks: “a JIT request, download checksum, process start, or runner exit
before job acceptance is retried with bounded exponential backoff … A runner
version rejection and an absent published checksum are terminal,
operator-actionable conditions, not retryable errors.”
So a checksum mismatch is retryable — the usual cause is a truncated or corrupted transfer, and the next attempt gets clean bytes — while an absent checksum is terminal, because retrying cannot make GitHub publish one. Getting this backwards in either direction is a real outage: retrying a version rejection turns a fixable condition into a silent loop, and treating a mismatch as terminal fails a cold start on a dropped packet.
Variants§
UnsupportedHost(UnsupportedHost)
This OS and architecture pair is not one the product documents. Refused before any request is made, let alone any download.
NoPackagePublished
GitHub publishes no package for this host. Never a reason to fall back
to a hardcoded URL — that is the substitution 07-security.md exists
to prevent.
ChecksumAbsent
GitHub published no usable sha256_checksum and no operator-pinned
digest is configured. Terminal: the agent fails closed
(05-infrastructure.md).
published says which of the three unusable shapes arrived. They are
kept apart because they are different facts about GitHub’s response —
c3 distinguishes absent from empty deliberately — and because an
operator reading this is entitled to the one that actually happened.
All three carry the same remedy, and that is the point of the variant:
every unusable shape routes to the operator-pinned digest. An earlier
version let a malformed value bypass the pin and then told the operator
to pin one, which was advice that could not work.
ChecksumMismatch
The bytes on disk are not the bytes GitHub published. The partial file is removed before this is returned, and nothing is extracted.
MalformedDigest
A digest — published or pinned — that is not 64 hex characters.
VersionRejected
GitHub refused this runner on version grounds. Terminal and
operator-actionable; see DownloadCatalog for who reports it.
The download metadata could not be read. Retryable.
Download
The package bytes could not be fetched. Retryable.
UnrecognisedVersion
A filename whose trailing segment is not a version.
UnsupportedArchive
A published filename that is neither a .zip nor a .tar.gz.
UnsafeArchiveEntry
An archive entry whose path escapes the directory being extracted into.
Verification runs before extraction, so these bytes are the bytes GitHub published and this should be unreachable. It is refused anyway: the cost is a path comparison, and the thing it prevents is an archive writing outside the cache root.
Extract
The archive could not be read or unpacked.
VersionInUse
A prune was refused because a live attempt still holds the version.
Fields
version: RunnerVersionstate: AttemptStateb1’s type, rendered by b1’s Display. This module had its own
nine-arm match producing the same nine strings; a second rendering
of someone else’s enum is a second thing to keep in step, and it
silently stops matching the moment a state is added.
VersionHeldByUnknownAttempt
A prune was refused because a lease names an attempt the caller did not
report. See PackageCache::prune for why this fails closed.
UnreadableLease
A lease file exists but cannot be understood, so what it holds is unknown and no prune can be shown to be safe.
WorkspaceInsideCache
A lease was refused because the attempt’s workspace is inside the cache.
NotInstalled
A lease or prune named a version that is not in the cache.
Fields
version: RunnerVersionIo
Exhausted
Every retry was spent on retryable failures.
Implementations§
Source§impl PackageError
impl PackageError
Sourcepub fn is_terminal(&self) -> bool
pub fn is_terminal(&self) -> bool
Whether this condition is terminal and operator-actionable rather than something a retry can clear.
Read the type-level documentation before changing any arm: the split is
fixed by 03-control-flows.md, not by taste.
Sourcepub fn failure_reason(&self) -> Option<FailureReason>
pub fn failure_reason(&self) -> Option<FailureReason>
The domain reason to journal, when this failure concludes an attempt.
b1 owns FailureReason and already names both of this module’s
terminal security conditions. Nothing here invents a second vocabulary
for them.
Sourcepub fn operator_action(&self) -> Option<&'static str>
pub fn operator_action(&self) -> Option<&'static str>
What the operator has to do. Every terminal condition has one; a retryable one has none, because the answer is “wait”.
Trait Implementations§
Source§impl Debug for PackageError
impl Debug for PackageError
Source§impl Display for PackageError
impl Display for PackageError
Source§impl Error for PackageError
impl Error for PackageError
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()