mcp_exec/
error.rs

1//! Structured error types produced across the resolution, verification, and runtime pipeline.
2
3use std::io;
4use std::time::Duration;
5
6use anyhow::Error as AnyError;
7use serde_json::Value;
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum ExecError {
12    #[error("failed to resolve component `{component}`: {source}")]
13    Resolve {
14        component: String,
15        #[source]
16        source: ResolveError,
17    },
18    #[error("artifact verification failed for `{component}`: {source}")]
19    Verification {
20        component: String,
21        #[source]
22        source: VerificationError,
23    },
24    #[error("runtime error while executing `{component}`: {source}")]
25    Runner {
26        component: String,
27        #[source]
28        source: RunnerError,
29    },
30    #[error("action `{action}` not found on component `{component}`")]
31    NotFound { component: String, action: String },
32    #[error("tool `{component}` returned error `{code}` for action `{action}`")]
33    Tool {
34        component: String,
35        action: String,
36        code: String,
37        payload: Value,
38    },
39}
40
41impl ExecError {
42    pub fn resolve(component: impl Into<String>, source: ResolveError) -> Self {
43        Self::Resolve {
44            component: component.into(),
45            source,
46        }
47    }
48
49    pub fn verification(component: impl Into<String>, source: VerificationError) -> Self {
50        Self::Verification {
51            component: component.into(),
52            source,
53        }
54    }
55
56    pub fn runner(component: impl Into<String>, source: RunnerError) -> Self {
57        Self::Runner {
58            component: component.into(),
59            source,
60        }
61    }
62
63    pub fn not_found(component: impl Into<String>, action: impl Into<String>) -> Self {
64        Self::NotFound {
65            component: component.into(),
66            action: action.into(),
67        }
68    }
69
70    pub fn tool_error(
71        component: impl Into<String>,
72        action: impl Into<String>,
73        code: impl Into<String>,
74        payload: Value,
75    ) -> Self {
76        Self::Tool {
77            component: component.into(),
78            action: action.into(),
79            code: code.into(),
80            payload,
81        }
82    }
83}
84
85#[derive(Debug, Error)]
86pub enum ResolveError {
87    #[error("component was not found in the configured store(s)")]
88    NotFound,
89    #[error("I/O error while reading artifact")]
90    Io(#[from] io::Error),
91    #[error("tool store error: {0}")]
92    Store(AnyError),
93}
94
95#[derive(Debug, Error)]
96pub enum VerificationError {
97    #[error("digest mismatch: expected {expected}, got {actual}")]
98    DigestMismatch { expected: String, actual: String },
99    #[error("artifact is unsigned and policy does not allow it")]
100    UnsignedRejected,
101}
102
103#[derive(Debug, Error)]
104pub enum RunnerError {
105    #[error("wasm execution timed out after {elapsed:?}")]
106    Timeout { elapsed: Duration },
107    #[error("wasmtime error: {0}")]
108    Wasmtime(#[from] wasmtime::Error),
109    #[error("serde error: {0}")]
110    Serde(#[from] serde_json::Error),
111    #[error("action `{action}` not implemented by the tool")]
112    ActionNotFound { action: String },
113    #[error("tool `{component}` transient failure: {message}")]
114    ToolTransient { component: String, message: String },
115    #[error("internal runner error: {0}")]
116    Internal(String),
117    #[error("runner is not implemented for this configuration")]
118    NotImplemented,
119}