Skip to main content

bob_rs/
error.rs

1//! Typed errors for the bob SDK.
2
3/// Why a bob-rs operation (install, keychain I/O, spawn) failed.
4///
5/// Each variant carries the real underlying error as a source — an
6/// [`std::io::Error`], a [`keyring::Error`], a [`serde_json::Error`], or a
7/// [`cli_stream::StreamError`] — rather than a pre-formatted string, so a
8/// consumer can inspect or downcast it (e.g. branch on `io::ErrorKind`, or
9/// recognise a `keyring::Error::NoEntry`). `#[non_exhaustive]` so adding a
10/// variant later isn't a breaking change.
11#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum BobError {
14    /// An OS-level I/O failure while running the installer — spooling the
15    /// embedded script to a tempfile, setting its mode, spawning `bash`, or
16    /// waiting on it. `context` names the step; `source` is the OS error.
17    #[error("{context}: {source}")]
18    Io {
19        /// Which install step failed (e.g. `"spawn install script"`).
20        context: &'static str,
21        /// The underlying OS error.
22        #[source]
23        source: std::io::Error,
24    },
25
26    /// A spawned install child didn't expose a piped stdout/stderr. Shouldn't
27    /// happen given `Stdio::piped()`, but `Child`'s accessors return `Option`,
28    /// so the case is represented rather than `unwrap`ped.
29    #[error("install child {stream} pipe was not captured")]
30    PipeNotCaptured {
31        /// Which stream was missing — `"stdout"` or `"stderr"`.
32        stream: &'static str,
33    },
34
35    /// The OS keychain rejected a read / write / delete of the API key.
36    #[error("keychain access failed: {0}")]
37    Keychain(#[from] keyring::Error),
38
39    /// Serializing the on-disk auth-state marker failed.
40    #[error("auth-state serialization failed: {0}")]
41    Serialize(#[from] serde_json::Error),
42
43    /// A caller-supplied argument was invalid (e.g. an empty API key).
44    #[error("{0}")]
45    Invalid(String),
46
47    /// The platform application-data directory couldn't be resolved, so the
48    /// auth-state marker has nowhere to live.
49    #[error("could not determine the application data directory")]
50    NoDataDir,
51
52    /// The subprocess engine failed to spawn or cancel bob.
53    #[error(transparent)]
54    Stream(#[from] cli_stream::StreamError),
55}