Skip to main content

hf_fetch_model/
error.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Error types for hf-fetch-model.
4//!
5//! All fallible operations in this crate return [`FetchError`].
6//! [`FileFailure`] provides structured per-file error reporting.
7
8use std::path::PathBuf;
9
10/// Errors that can occur during model fetching.
11#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum FetchError {
14    /// The hf-hub API returned an error.
15    #[error("hf-hub API error: {0}")]
16    Api(#[from] hf_hub::api::tokio::ApiError),
17
18    /// An I/O error occurred while accessing the local filesystem.
19    #[error("I/O error at {path}: {source}")]
20    Io {
21        /// The path that caused the error.
22        path: PathBuf,
23        /// The underlying I/O error.
24        source: std::io::Error,
25    },
26
27    /// The repository was not found or is inaccessible.
28    #[error("repository not found: {repo_id}")]
29    RepoNotFound {
30        /// The repository identifier that was not found.
31        repo_id: String,
32    },
33
34    /// Authentication failed (missing or invalid token).
35    #[error("authentication failed: {reason}")]
36    Auth {
37        /// Description of the authentication failure.
38        reason: String,
39    },
40
41    /// An invalid glob pattern was provided for filtering.
42    #[error("invalid glob pattern: {pattern}: {reason}")]
43    InvalidPattern {
44        /// The glob pattern that failed to parse.
45        pattern: String,
46        /// Description of the parse error.
47        reason: String,
48    },
49
50    /// SHA256 checksum mismatch after download.
51    #[error("checksum mismatch for {filename}: expected {expected}, got {actual}")]
52    Checksum {
53        /// The filename that failed verification.
54        filename: String,
55        /// The expected SHA256 hex digest.
56        expected: String,
57        /// The actual SHA256 hex digest computed from the file.
58        actual: String,
59    },
60
61    /// A download operation timed out.
62    #[error("timeout downloading {filename} after {seconds}s")]
63    Timeout {
64        /// The filename that timed out.
65        filename: String,
66        /// The timeout duration in seconds.
67        seconds: u64,
68    },
69
70    /// One or more files failed to download.
71    ///
72    /// Contains the successful path and a list of per-file failures.
73    #[error("{} file(s) failed to download", failures.len())]
74    PartialDownload {
75        /// The snapshot directory (if any files succeeded).
76        path: Option<PathBuf>,
77        /// Per-file failure details.
78        failures: Vec<FileFailure>,
79    },
80
81    /// A chunked (multi-connection) download failed.
82    #[error("chunked download failed for {filename}: {reason}")]
83    ChunkedDownload {
84        /// The filename that failed.
85        filename: String,
86        /// Description of the failure.
87        reason: String,
88    },
89
90    /// An HTTP request to the `HuggingFace` API failed.
91    #[error("HTTP error: {0}")]
92    Http(String),
93
94    /// An invalid argument was provided.
95    #[error("{0}")]
96    InvalidArgument(String),
97}
98
99/// A per-file download failure with structured context.
100#[derive(Debug, Clone)]
101pub struct FileFailure {
102    /// The filename that failed.
103    pub filename: String,
104    /// Human-readable description of the failure.
105    pub reason: String,
106    /// Whether this failure is likely to succeed on retry.
107    pub retryable: bool,
108}
109
110impl std::fmt::Display for FileFailure {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(
113            f,
114            "{}: {} (retryable: {})",
115            self.filename, self.reason, self.retryable
116        )
117    }
118}