Skip to main content

stackql_mcp/
error.rs

1use std::fmt;
2use std::path::PathBuf;
3
4/// Errors produced while acquiring, verifying, or running the embedded server.
5#[derive(Debug)]
6#[non_exhaustive]
7pub enum Error {
8    /// No .mcpb bundle is published for the host OS/arch.
9    UnsupportedPlatform {
10        os: &'static str,
11        arch: &'static str,
12    },
13    /// The home directory could not be resolved (HOME / USERPROFILE unset).
14    NoHomeDir,
15    /// Downloading the bundle failed.
16    Http { url: String, message: String },
17    /// The downloaded bundle did not match the sha256 pin baked into the crate.
18    ChecksumMismatch {
19        bundle: String,
20        expected: String,
21        actual: String,
22    },
23    /// The .mcpb bundle is malformed (bad zip, missing or invalid manifest).
24    Bundle(String),
25    /// Filesystem error.
26    Io(std::io::Error),
27    /// The server process could not be spawned.
28    Spawn(std::io::Error),
29    /// MCP handshake or client error.
30    Mcp(String),
31    /// A path given via an env override or builder option does not exist.
32    OverrideNotFound { what: &'static str, path: PathBuf },
33}
34
35impl fmt::Display for Error {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Error::UnsupportedPlatform { os, arch } => {
39                write!(f, "no stackql mcp bundle is published for {os}/{arch}")
40            }
41            Error::NoHomeDir => {
42                write!(
43                    f,
44                    "could not resolve the home directory (HOME / USERPROFILE unset)"
45                )
46            }
47            Error::Http { url, message } => write!(f, "download of {url} failed: {message}"),
48            Error::ChecksumMismatch {
49                bundle,
50                expected,
51                actual,
52            } => write!(
53                f,
54                "sha256 mismatch for {bundle}: expected {expected}, got {actual}"
55            ),
56            Error::Bundle(msg) => write!(f, "invalid .mcpb bundle: {msg}"),
57            Error::Io(e) => write!(f, "io error: {e}"),
58            Error::Spawn(e) => write!(f, "failed to spawn the stackql mcp server: {e}"),
59            Error::Mcp(msg) => write!(f, "mcp client error: {msg}"),
60            Error::OverrideNotFound { what, path } => {
61                write!(
62                    f,
63                    "{what} points to {} which does not exist",
64                    path.display()
65                )
66            }
67        }
68    }
69}
70
71impl std::error::Error for Error {
72    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
73        match self {
74            Error::Io(e) | Error::Spawn(e) => Some(e),
75            _ => None,
76        }
77    }
78}
79
80impl From<std::io::Error> for Error {
81    fn from(e: std::io::Error) -> Self {
82        Error::Io(e)
83    }
84}
85
86pub type Result<T> = std::result::Result<T, Error>;