canic_core/
error.rs

1use crate::access::AccessError;
2use derive_more::Display;
3use thiserror::Error as ThisError;
4
5///
6/// InternalError
7///
8/// Internal, structured error type.
9///
10/// This error:
11/// - is NOT Candid-exposed
12/// - is NOT stable across versions
13/// - may evolve freely
14///
15/// All canister endpoints must convert this into a public error envelope
16/// defined in dto/.
17///
18
19#[derive(Debug, ThisError)]
20#[error("{message}")]
21pub(crate) struct InternalError {
22    class: InternalErrorClass,
23    origin: InternalErrorOrigin,
24    message: String,
25}
26
27impl InternalError {
28    pub fn new(
29        class: InternalErrorClass,
30        origin: InternalErrorOrigin,
31        message: impl Into<String>,
32    ) -> Self {
33        Self {
34            class,
35            origin,
36            message: message.into(),
37        }
38    }
39
40    pub fn domain(origin: InternalErrorOrigin, message: impl Into<String>) -> Self {
41        Self::new(InternalErrorClass::Domain, origin, message)
42    }
43
44    pub fn invariant(origin: InternalErrorOrigin, message: impl Into<String>) -> Self {
45        Self::new(InternalErrorClass::Invariant, origin, message)
46    }
47
48    pub fn infra(origin: InternalErrorOrigin, message: impl Into<String>) -> Self {
49        Self::new(InternalErrorClass::Infra, origin, message)
50    }
51
52    pub fn ops(origin: InternalErrorOrigin, message: impl Into<String>) -> Self {
53        Self::new(InternalErrorClass::Ops, origin, message)
54    }
55
56    pub fn workflow(origin: InternalErrorOrigin, message: impl Into<String>) -> Self {
57        Self::new(InternalErrorClass::Workflow, origin, message)
58    }
59
60    pub const fn class(&self) -> InternalErrorClass {
61        self.class
62    }
63
64    pub const fn origin(&self) -> InternalErrorOrigin {
65        self.origin
66    }
67
68    #[must_use]
69    pub const fn log_fields(&self) -> (InternalErrorClass, InternalErrorOrigin) {
70        (self.class, self.origin)
71    }
72}
73
74impl From<AccessError> for InternalError {
75    fn from(err: AccessError) -> Self {
76        Self::new(
77            InternalErrorClass::Access,
78            InternalErrorOrigin::Access,
79            err.to_string(),
80        )
81    }
82}
83
84///
85/// InternalErrorClass
86///
87
88#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)]
89pub(crate) enum InternalErrorClass {
90    Access,
91    Domain,
92    Infra,
93    Ops,
94    Workflow,
95    Invariant,
96}
97
98///
99/// InternalErrorOrigin
100///
101
102#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)]
103pub(crate) enum InternalErrorOrigin {
104    Access,
105    Config,
106    Domain,
107    Infra,
108    Ops,
109    Storage,
110    Workflow,
111}