Files
arr/crates/arr-meta/src/error.rs
T
2026-08-24 18:56:59 +01:00

61 lines
1.9 KiB
Rust

//! Errors the TMDB client can produce.
use std::time::Duration;
/// Result alias for every fallible operation in this crate.
pub type Result<T> = std::result::Result<T, Error>;
/// Everything that can go wrong talking to TMDB.
///
/// The distinction that matters to callers is between "this title does not
/// exist" ([`Error::NotFound`]), "back off" ([`Error::RateLimited`]) and
/// "TMDB is unreachable" ([`Error::Transport`]) — the last is a §9.5 *broken*
/// notification, the first two are not.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// The request never completed: DNS, TLS, connection or timeout.
#[error("TMDB request failed")]
Transport(#[from] reqwest::Error),
/// TMDB rejected the API key.
#[error("TMDB rejected the API key")]
Unauthorized,
/// TMDB has no record of the thing that was asked for.
#[error("TMDB has no record of {resource}")]
NotFound {
/// The logical resource that was requested, e.g. `movie/693134`.
resource: String,
},
/// TMDB is rate limiting. `retry_after` is the `Retry-After` header when
/// TMDB sent one.
#[error("TMDB rate limit reached")]
RateLimited {
/// How long TMDB asked us to wait, when it said.
retry_after: Option<Duration>,
},
/// Any other non-success status.
#[error("TMDB returned HTTP {status}")]
Unexpected {
/// The HTTP status code.
status: u16,
/// The response body, truncated to something loggable.
body: String,
},
/// The response parsed as JSON but not into the shape expected.
#[error("TMDB response did not match the expected shape")]
Decode(#[from] serde_json::Error),
/// The configured base URL is not a URL.
#[error("invalid TMDB base URL: {0}")]
BaseUrl(String),
/// The on-disk response cache directory could not be created.
#[error("TMDB cache directory: {0}")]
Cache(#[from] std::io::Error),
}