Skip to main content

Mountain/Error/
CoreError.rs

1//! # Core Error Types (local, superseded)
2//!
3//! Base building blocks of Mountain's error taxonomy. Defines five
4//! core types: [`ErrorSeverity`], [`ErrorKind`], [`ErrorContext`],
5//! [`MountainError`], and a generic `Result<T>` alias. The five
6//! per-domain sibling modules (`IPCError`, `FileSystemError`,
7//! `ConfigurationError`, `ProviderError`, `ServiceError`) wrap an
8//! `ErrorContext` and converge on `MountainError` via a `From` impl.
9//!
10//! ## Status
11//!
12//! Zero callers as of 2026-05-02. These types are superseded by
13//! `CommonLibrary::Error::CommonError`. The module remains in place
14//! so that a future migration back to per-domain error types can
15//! pick up the existing constructors without rebuilding them. Do not
16//! add new callers - use `CommonError` directly.
17
18use std::{error::Error as StdError, fmt};
19
20use serde::{Deserialize, Serialize};
21
22/// Severity level of an error, used to categorize the impact of
23/// an error from informational to critical.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
25pub enum ErrorSeverity {
26	/// Informational: no action required.
27	Info = 0,
28
29	/// Warning: something unexpected but non-blocking.
30	Warning = 1,
31
32	/// Error: operation failed and requires attention.
33	Error = 2,
34
35	/// Critical: system-level failure, immediate action needed.
36	Critical = 3,
37}
38
39impl fmt::Display for ErrorSeverity {
40	fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
41		match self {
42			ErrorSeverity::Info => write!(f, "Info"),
43
44			ErrorSeverity::Warning => write!(f, "Warning"),
45
46			ErrorSeverity::Error => write!(f, "Error"),
47
48			ErrorSeverity::Critical => write!(f, "Critical"),
49		}
50	}
51}
52
53/// Top-level error category assigned to every error at construction
54/// time. Used for routing, filtering, and aggregation in log sinks.
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
56pub enum ErrorKind {
57	/// Inter-process or inter-service communication failure.
58	IPC,
59
60	/// File or directory operation failure.
61	FileSystem,
62
63	/// Configuration read/write/validation failure.
64	Configuration,
65
66	/// Sidecar or long-running service lifecycle failure.
67	Service,
68
69	/// Capability provider (file, terminal, document, etc.) failure.
70	Provider,
71
72	/// Unclassified error.
73	Other,
74}
75
76impl fmt::Display for ErrorKind {
77	fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
78		match self {
79			ErrorKind::IPC => write!(f, "IPC"),
80
81			ErrorKind::FileSystem => write!(f, "FileSystem"),
82
83			ErrorKind::Configuration => write!(f, "Configuration"),
84
85			ErrorKind::Service => write!(f, "Service"),
86
87			ErrorKind::Provider => write!(f, "Provider"),
88
89			ErrorKind::Other => write!(f, "Other"),
90		}
91	}
92}
93
94/// Companion metadata attached to every [`MountainError`]. Carries
95/// the human-readable message, categorization via [`ErrorKind`] and
96/// [`ErrorSeverity`], and optional operation/component context for
97/// log aggregation.
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ErrorContext {
100	/// Human-readable description of what went wrong.
101	pub message:String,
102
103	/// Category of the failure (e.g. `IPC`, `FileSystem`).
104	pub kind:ErrorKind,
105
106	/// Impact level (Info through Critical).
107	pub severity:ErrorSeverity,
108
109	/// Operation that was in progress when the error occurred, if known.
110	pub operation:Option<String>,
111
112	/// Component or module that raised the error, if known.
113	pub component:Option<String>,
114}
115
116impl ErrorContext {
117	/// Creates a new context with default kind and severity.
118	pub fn new(message:impl Into<String>) -> Self {
119		Self {
120			message:message.into(),
121
122			kind:ErrorKind::Other,
123
124			severity:ErrorSeverity::Error,
125
126			operation:None,
127
128			component:None,
129		}
130	}
131
132	pub fn with_kind(mut self, kind:ErrorKind) -> Self {
133		self.kind = kind;
134
135		self
136	}
137
138	pub fn with_severity(mut self, severity:ErrorSeverity) -> Self {
139		self.severity = severity;
140
141		self
142	}
143
144	pub fn with_operation(mut self, operation:impl Into<String>) -> Self {
145		self.operation = Some(operation.into());
146
147		self
148	}
149
150	pub fn with_component(mut self, component:impl Into<String>) -> Self {
151		self.component = Some(component.into());
152
153		self
154	}
155}
156
157impl fmt::Display for ErrorContext {
158	fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
159		write!(f, "[{}][{}] {}", self.kind, self.severity, self.message)
160	}
161}
162
163/// Base error type for Mountain, wrapping an [`ErrorContext`] with
164/// optional raw source text and an optional stack trace snapshot.
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct MountainError {
167	/// Categorization, severity, and human-readable message.
168	pub context:ErrorContext,
169
170	/// Raw source text or underlying cause, if available.
171	pub source:Option<String>,
172
173	/// Stack trace captured at the error site, if available.
174	pub stack_trace:Option<String>,
175}
176
177impl MountainError {
178	/// Creates a new error from the given context.
179	pub fn new(context:ErrorContext) -> Self { Self { context, source:None, stack_trace:None } }
180
181	/// Attaches a raw source string (e.g. the underlying error's display
182	/// output).
183	pub fn with_source(mut self, source:impl Into<String>) -> Self {
184		self.source = Some(source.into());
185
186		self
187	}
188
189	/// Attaches a stack trace snapshot for post-mortem debugging.
190	pub fn with_stack_trace(mut self, stack_trace:impl Into<String>) -> Self {
191		self.stack_trace = Some(stack_trace.into());
192
193		self
194	}
195
196	/// Returns the human-readable message.
197	pub fn message(&self) -> &str { &self.context.message }
198
199	/// Returns the error kind.
200	pub fn kind(&self) -> ErrorKind { self.context.kind }
201
202	/// Returns the severity level.
203	pub fn severity(&self) -> ErrorSeverity { self.context.severity }
204
205	/// Returns `true` when the severity is `Critical`.
206	pub fn is_critical(&self) -> bool { self.context.severity == ErrorSeverity::Critical }
207}
208
209impl fmt::Display for MountainError {
210	fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
211		write!(f, "{}", self.context)?;
212
213		if let Some(source) = &self.source {
214			write!(f, " ({})", source)?;
215		}
216
217		Ok(())
218	}
219}
220
221impl StdError for MountainError {}
222
223impl From<ErrorContext> for MountainError {
224	fn from(context:ErrorContext) -> Self { Self::new(context) }
225}
226
227/// Result type alias for Mountain operations.
228pub type Result<T> = std::result::Result<T, MountainError>;