yfinance/error.rs
1//! Error and result types.
2
3use std::fmt;
4
5/// Convenient `Result` alias used throughout the crate.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// All errors produced by this crate.
9#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum Error {
12 /// Underlying HTTP transport failure.
13 #[error("http error: {0}")]
14 Http(#[from] reqwest::Error),
15
16 /// JSON decoding failure.
17 #[error("json error: {0}")]
18 Json(#[from] serde_json::Error),
19
20 /// URL parsing failure.
21 #[error("url error: {0}")]
22 Url(#[from] url::ParseError),
23
24 /// Yahoo returned a non-success status code.
25 #[error("yahoo returned status {status}: {message}")]
26 Status {
27 /// HTTP status code.
28 status: u16,
29 /// Best-effort message extracted from the response body.
30 message: String,
31 },
32
33 /// Yahoo's chart/v8 endpoint returned an explicit error payload.
34 #[error("yahoo error [{code}] for {symbol}: {description}")]
35 Yahoo {
36 /// Symbol that triggered the error.
37 symbol: String,
38 /// Yahoo error code (e.g. `Not Found`).
39 code: String,
40 /// Human-readable description.
41 description: String,
42 },
43
44 /// We got a 429 from Yahoo and exhausted retry budget.
45 #[error("rate limited by Yahoo (HTTP 429)")]
46 RateLimited,
47
48 /// Could not obtain an authenticated session (cookie + crumb).
49 #[error("could not authenticate with Yahoo: {0}")]
50 Auth(String),
51
52 /// The ticker symbol is missing or delisted.
53 #[error("ticker `{ticker}` not found: {reason}")]
54 TickerMissing {
55 /// The requested symbol.
56 ticker: String,
57 /// Reason supplied by the upstream API or our parser.
58 reason: String,
59 },
60
61 /// The ticker has no timezone info — usually means delisted.
62 #[error("ticker `{0}` has no timezone metadata")]
63 TimezoneMissing(String),
64
65 /// No price data returned for the requested period/interval.
66 #[error("no prices returned for `{ticker}` ({hint})")]
67 PricesMissing {
68 /// The requested symbol.
69 ticker: String,
70 /// Human-readable hint about why data was missing.
71 hint: String,
72 },
73
74 /// The requested period/interval combination is not allowed.
75 #[error("invalid period/interval for `{ticker}`: {reason}")]
76 InvalidPeriod {
77 /// The requested symbol.
78 ticker: String,
79 /// Why the combination is invalid.
80 reason: String,
81 },
82
83 /// A response field had an unexpected shape.
84 #[error("unexpected response shape: {0}")]
85 UnexpectedResponse(String),
86
87 /// A required argument was invalid.
88 #[error("invalid argument: {0}")]
89 InvalidArgument(String),
90
91 /// Catch-all for unexpected I/O.
92 #[error(transparent)]
93 Io(#[from] std::io::Error),
94}
95
96impl Error {
97 /// Construct an [`Error::UnexpectedResponse`] with a formatted message.
98 pub fn unexpected(msg: impl fmt::Display) -> Self {
99 Error::UnexpectedResponse(msg.to_string())
100 }
101
102 /// Construct an [`Error::InvalidArgument`] with a formatted message.
103 pub fn invalid(msg: impl fmt::Display) -> Self {
104 Error::InvalidArgument(msg.to_string())
105 }
106}