Skip to main content

DownloadError

Enum DownloadError 

Source
pub enum DownloadError {
    Transport {
        provider: String,
        reason: String,
    },
    Timeout {
        provider: String,
    },
    Verify(VerifyError),
    NoProviders {
        needed: usize,
    },
    NotFound {
        content: String,
    },
    MetadataProbeFailed {
        content: String,
        holders: usize,
        reasons: Vec<String>,
    },
    PagedPrologueUnsupported {
        provider: String,
        chunk_count: u64,
        delivered: u64,
    },
    Cancelled,
    State(String),
    Sink(String),
    NotDownloadable,
    TaskEnded,
}
Expand description

An error from a download operation.

Variants§

§

Transport

A transport-level failure fetching from one provider (connect failed, stream dropped, availability/range RPC errored, timeout). Carries the reason as text. Recoverable: the orchestrator marks the provider suspect and re-queues the range to another holder.

Fields

§provider: String

The provider peer_id (64-hex) the failure came from.

§reason: String

The underlying reason (stable, greppable text).

§

Timeout

A range fetch exceeded the configured per-range timeout (DownloadConfig::range_timeout) — a too-slow or stalled source. Recoverable: the range is re-queued to another holder and the slow source is backed off (its TimedOut outcome is reported to the selector).

Fields

§provider: String

The provider peer_id (64-hex) whose fetch timed out.

§

Verify(VerifyError)

A fetched range failed integrity verification. Recoverable: the bad range is discarded and re-fetched from a different provider, and the serving provider is penalized.

The wrapped reason is SANITIZED here for the same reason a transport reason is: a verify failure routinely quotes peer-reported metadata (a first-frame root, a declared length), so it is untrusted text arriving through a different door.

§

NoProviders

A still-needed range has no live provider left to fetch it from — every known holder has been tried + failed and a fresh find_providers discovered no more. This is terminal for the download (there is nowhere left to get the missing bytes).

Fields

§needed: usize

How many ranges were still missing when the provider set was exhausted.

§

NotFound

The content could not be fetched at all — either find_providers returned no holders, or no located holder could answer the metadata probe. Terminal.

content names the content id AND which of those two steps failed: the message must never blame discovery for a probe failure (that ambiguity cost four #1586 investigations).

Fields

§content: String

The content id that could not be fetched, plus the step that failed.

§

MetadataProbeFailed

Holders WERE located and confirmed, but not one of them could seed the resource layout. Terminal.

This is the named replacement for reporting that outcome as a generic NotFound. The two failures are not the same event and must not read the same: “nobody has this content” is a discovery result, while “several holders have it and every one of them served metadata this reader cannot use” is a compatibility or hostility result, and only the second is actionable by whoever operates the holders. Collapsing them cost four separate #1586 investigations.

reasons carries the per-holder cause, which was previously written to a tracing::debug! and then dropped — so the one fact that identifies the fault survived only if debug logging happened to be on.

Fields

§content: String

The content id whose layout could not be established.

§holders: usize

How many confirmed holders were probed.

§reasons: Vec<String>

One peer_id: reason line per probed holder, in probe order.

§

PagedPrologueUnsupported

The resource’s chunk_lens paged prologue could not be COMPLETED — the stream ended short of the declared chunk_count, or a first frame that declared no multi-page layout was followed by a frame paging one. Recoverable per holder: the range is retried elsewhere and the adoption path probes the next holder.

§Fail-closed, not a reader limitation

This reader DOES reassemble a paged prologue (SPEC.md §2.2), so a conforming multi-page holder reads end-to-end. The error is raised only when the layout stays INCOMPLETE — a decrypt-input array short of chunk_count would decrypt every chunk to garbage, so it is refused rather than adopted partial. It reports the declared count and the entries delivered so a short prologue is distinguishable from “nobody holds this content”. (A page that violates a placement rule — misaligned, duplicated, overshooting — surfaces instead as a recoverable Transport naming the broken rule.)

Fields

§provider: String

The provider peer_id (64-hex) whose layout could not be assembled.

§chunk_count: u64

The whole array’s declared entry count.

§delivered: u64

How many entries had been delivered when the reader gave up.

§

Cancelled

The download was cancelled via DownloadHandle::cancel. Terminal (by request).

§

State(String)

Persisting or loading resume state failed. Carries the reason.

§

Sink(String)

The sink (store-write path) rejected a write. Carries the reason.

§

NotDownloadable

The requested content id cannot be downloaded as a byte stream — a bare store id names a whole store (many capsules), not a single resource/capsule to fetch. Supply a root/capsule or resource content id.

§

TaskEnded

The orchestrator task ended unexpectedly (its channel closed before a terminal result). This indicates a bug or an aborted runtime, not a normal download outcome.

Implementations§

Source§

impl DownloadError

Source

pub fn transport(provider: impl Into<String>, reason: impl Display) -> Self

Build a DownloadError::Transport for provider from anything displayable.

Source

pub fn sink(reason: impl Display) -> Self

Build a DownloadError::Sink from anything displayable.

Source

pub fn state(reason: impl Display) -> Self

Build a DownloadError::State from anything displayable.

Source

pub fn is_recoverable(&self) -> bool

Whether this error is recoverable per range (the download can continue by retrying the range elsewhere) rather than terminal for the whole download.

PagedPrologueUnsupported is recoverable for the same reason a transport failure is: it rules out ONE holder’s stream, not the content. The other new variants are terminal — each already reports that every holder was tried.

Source

pub fn attributed_to(self, peer_id: &str) -> Self

Fill in an as-yet-unattributed provider with the peer the failure came from, leaving every other variant untouched.

The pure reassembly core cannot know which peer it is reading, so it raises errors with an empty provider for the transport layer to stamp. Stamping must not be done by WRAPPING, which is what this replaced: re-wrapping every reassembly failure into a Transport flattened the typed ones, so a variant the reassembler raised deliberately — and that is_recoverable treats specially — could never be observed by a caller.

An already-attributed error is returned unchanged, so stamping twice cannot relabel a failure onto the wrong peer.

Trait Implementations§

Source§

impl Debug for DownloadError

Debug delegates to the SANITIZING Display rather than printing raw fields.

Debug is not a developer-only rendering in practice: tracing’s ?field, a {:?} in a log line, and every unwrap/expect panic message emit it. A derived Debug would print the untrusted provider / reason / verify text verbatim — unbounded, with markup intact — bypassing the very sanitization Display applies. One rendering, one door.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for DownloadError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for DownloadError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<HopPathError> for DownloadError

Source§

fn from(e: HopPathError) -> Self

Converts to this type from the input type.
Source§

impl From<VerifyError> for DownloadError

Source§

fn from(source: VerifyError) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more