//! Errors the TMDB client can produce. use std::time::Duration; /// Result alias for every fallible operation in this crate. pub type Result = std::result::Result; /// 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, }, /// 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), }