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}