Skip to main content

ic_memory/runtime/
error.rs

1use crate::{
2    LedgerCommitError, PolicyIdentity, PolicyIdentityError, StableCellLedgerError,
3    registry::StaticMemoryDeclarationError,
4    slot::{MemoryManagerRangeAuthorityError, MemoryManagerSlotError},
5};
6
7///
8/// RuntimeGrowError
9///
10/// Failure to grow a runtime memory before assigning new manager buckets.
11/// Ordinary capacity failures preserve virtual extents and manager metadata.
12/// Backing traps and partial writes remain outside this guarantee.
13///
14
15#[non_exhaustive]
16#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
17pub enum RuntimeGrowError {
18    /// The requested virtual extent overflows the page count.
19    #[error("virtual memory page count overflows")]
20    ArithmeticOverflow,
21    /// The sole manager has insufficient bucket slots.
22    #[error("growth requires {required_buckets} buckets, exceeding capacity {capacity}")]
23    BucketExhausted {
24        required_buckets: u64,
25        capacity: u16,
26    },
27    /// The backing memory refused the physical capacity reservation.
28    #[error("backing memory refused growth by {additional_pages} pages")]
29    BackingRefused { additional_pages: u64 },
30    /// Growth re-entered while another handle held a capacity reservation.
31    #[error("runtime memory growth is already in progress")]
32    ReentrantAccess,
33    /// The manager refused growth despite the runtime's successful preflight.
34    #[error("memory manager refused preflighted growth")]
35    ManagerRefused,
36}
37
38///
39/// RuntimeConstructionError
40///
41/// Failure to construct a memory runtime without overwriting unrecognized
42/// backing memory.
43///
44
45#[non_exhaustive]
46#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
47pub enum RuntimeConstructionError {
48    /// Zero pages cannot form a bucket.
49    #[error("bucket size must be nonzero")]
50    InvalidBucketSize,
51    /// Explicit policy differs from the actual durable setting.
52    #[error("persisted bucket size {persisted} pages differs from requested {requested}")]
53    BucketSizeMismatch { persisted: u16, requested: u16 },
54    /// Persisted manager metadata failed bounded validation.
55    #[error(transparent)]
56    Layout(#[from] super::MemoryManagerLayoutError),
57    /// Nonempty backing memory does not contain a `MemoryManager` header.
58    #[error(
59        "nonempty backing memory is not an ic-stable-structures MemoryManager \
60         (expected magic 'MGR', found bytes {observed_magic:?})"
61    )]
62    ForeignMemory {
63        /// First three bytes found in the nonempty backing memory.
64        observed_magic: [u8; 3],
65    },
66    /// Backing memory contains an unsupported `MemoryManager` layout version.
67    #[error(
68        "unsupported ic-stable-structures MemoryManager layout version {observed}; \
69         expected {supported}"
70    )]
71    UnsupportedMemoryManagerVersion {
72        /// Version byte found after the `MemoryManager` magic.
73        observed: u8,
74        /// Version supported by the pinned `ic-stable-structures` dependency.
75        supported: u8,
76    },
77}
78
79///
80/// RuntimeStateError
81///
82/// Failure to enter or maintain one memory runtime's in-memory lifecycle.
83///
84
85#[non_exhaustive]
86#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
87pub enum RuntimeStateError {
88    /// This thread's default runtime could not safely claim its backing memory.
89    #[error(transparent)]
90    Construction(#[from] RuntimeConstructionError),
91    /// A default-runtime operation re-entered while that TLS runtime was borrowed.
92    #[error("ic-memory default runtime is already borrowed by an active operation")]
93    ReentrantAccess,
94    /// The thread-local default runtime is being destroyed and cannot be entered.
95    #[error("ic-memory default runtime is unavailable during thread-local destruction")]
96    Unavailable,
97    /// Internal runtime lifecycle state was inconsistent.
98    #[error("ic-memory runtime lifecycle is internally inconsistent")]
99    InconsistentLifecycle,
100}
101
102///
103/// RuntimeBootstrapError
104///
105/// Failure to bootstrap one `MemoryRuntime`.
106///
107
108#[non_exhaustive]
109#[derive(Debug, thiserror::Error)]
110pub enum RuntimeBootstrapError<P> {
111    /// A known-only historical selection failed before commitment.
112    #[error(transparent)]
113    Admission(#[from] super::BootstrapAdmissionError),
114    /// Consumer identity or key-set admission rejected this attempt.
115    #[error("bootstrap admission policy rejected recovered allocation metadata")]
116    AdmissionPolicy(P),
117    #[error(transparent)]
118    Resolution(#[from] MemoryResolutionError),
119    /// The policy did not provide a valid bounded semantic identity.
120    #[error(transparent)]
121    PolicyIdentity(#[from] PolicyIdentityError),
122    /// A bootstrapped runtime was called with a different declaration snapshot.
123    #[error("runtime bootstrap declaration snapshot differs from the established binding")]
124    DeclarationSnapshotMismatch,
125    /// A bootstrapped runtime was called with a different policy identity.
126    #[error("runtime bootstrap policy identity changed from {established:?} to {requested:?}")]
127    PolicyIdentityMismatch {
128        /// Policy identity established by successful bootstrap.
129        established: PolicyIdentity,
130        /// Policy identity supplied by the repeated call.
131        requested: PolicyIdentity,
132    },
133    /// Linked-program declaration snapshot sealing failed.
134    #[error(transparent)]
135    Registry(#[from] StaticMemoryDeclarationError),
136    /// Runtime ledger genesis construction failed.
137    #[error(transparent)]
138    LedgerIntegrity(#[from] crate::LedgerIntegrityError),
139    /// Protected ledger recovery or commit failed.
140    #[error(transparent)]
141    LedgerCommit(#[from] crate::LedgerCommitError),
142    /// Stable-cell ledger storage is corrupt before protected recovery can run.
143    #[error(transparent)]
144    StableCellLedger(#[from] StableCellLedgerError),
145    /// The encoded stable-cell ledger record exceeds its bounded size ceiling.
146    #[error("stable-cell ledger record size {value_size} cannot be written to stable memory")]
147    StableCellLedgerWriteTooLarge {
148        /// Encoded stable-cell ledger record size in bytes.
149        value_size: usize,
150    },
151    /// Stable-cell ledger capacity reservation failed before commitment.
152    #[error(transparent)]
153    LedgerGrowth(#[from] RuntimeGrowError),
154    /// Declaration validation failed.
155    #[error(transparent)]
156    Validation(#[from] crate::AllocationValidationError<RuntimePolicyError<P>>),
157    /// Validated declarations could not be staged.
158    #[error(transparent)]
159    Staging(#[from] crate::AllocationStageError),
160    /// Runtime lifecycle or default TLS access failed.
161    #[error(transparent)]
162    State(#[from] RuntimeStateError),
163}
164
165///
166/// RuntimeOpenError
167///
168/// Failure to open an allocation through one memory runtime.
169///
170
171#[non_exhaustive]
172#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
173pub enum RuntimeOpenError {
174    /// This runtime has not published committed allocations.
175    #[error("ic-memory runtime has not completed bootstrap validation")]
176    NotBootstrapped,
177    /// Runtime lifecycle or default TLS access failed.
178    #[error(transparent)]
179    State(#[from] RuntimeStateError),
180    /// Stable-key grammar failure.
181    #[error(transparent)]
182    StableKey(#[from] crate::StableKeyError),
183    /// The stable key was not present in this runtime's committed declaration set.
184    #[error("stable key '{0}' was not committed by ic-memory runtime bootstrap")]
185    StableKeyNotCommitted(String),
186    /// Runtime governance stable keys are internal and cannot be opened publicly.
187    #[error("stable key '{stable_key}' is reserved for ic-memory runtime governance")]
188    ReservedStableKey {
189        /// Reserved stable key.
190        stable_key: String,
191    },
192    /// The committed slot is not a usable `MemoryManager` ID.
193    #[error(transparent)]
194    MemoryManagerSlot(#[from] MemoryManagerSlotError),
195    /// The requested memory ID does not match the committed stable-key binding.
196    #[error(
197        "stable key '{stable_key}' is committed for MemoryManager ID {committed_id}, not requested ID {requested_id}"
198    )]
199    MemoryIdMismatch {
200        /// Stable key being opened.
201        stable_key: String,
202        /// Committed MemoryManager ID.
203        committed_id: u8,
204        /// Requested MemoryManager ID.
205        requested_id: u8,
206    },
207}
208
209///
210/// RuntimeDiagnosticError
211///
212/// Failure to build diagnostics for one memory runtime.
213///
214
215#[non_exhaustive]
216#[derive(Debug, thiserror::Error)]
217pub enum RuntimeDiagnosticError {
218    /// Persisted manager metadata is invalid or unsupported.
219    #[error(transparent)]
220    Construction(#[from] RuntimeConstructionError),
221    /// Current binding metadata exceeds the fixed usable ID domain.
222    #[error("allocation bindings exceed the bounded manager domain")]
223    AllocationBound,
224    /// This runtime has not opened and validated its ledger cell.
225    #[error("ic-memory runtime has not completed bootstrap validation")]
226    NotBootstrapped,
227    /// Linked-program declaration snapshot sealing failed.
228    #[error(transparent)]
229    Registry(#[from] StaticMemoryDeclarationError),
230    /// Runtime lifecycle or default TLS access failed.
231    #[error(transparent)]
232    State(#[from] RuntimeStateError),
233    /// The recovered allocation ledger failed protected commit validation.
234    #[error(transparent)]
235    LedgerCommit(#[from] LedgerCommitError),
236    /// Stable-cell ledger storage is corrupt before protected recovery can run.
237    #[error(transparent)]
238    StableCellLedger(#[from] StableCellLedgerError),
239    /// A committed allocation slot was not a usable `MemoryManager` ID.
240    #[error(transparent)]
241    MemoryManagerSlot(#[from] MemoryManagerSlotError),
242}
243
244///
245/// RuntimePolicyError
246///
247/// Failure in generic runtime range policy or caller-supplied policy.
248///
249
250#[non_exhaustive]
251#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
252pub enum RuntimePolicyError<P> {
253    /// Runtime range authority rejected the declaration.
254    #[error(transparent)]
255    Range(#[from] MemoryManagerRangeAuthorityError),
256    /// Runtime metadata is internally inconsistent.
257    #[error("runtime declaration metadata is missing for stable key '{0}'")]
258    MissingDeclarationMetadata(String),
259    /// `ic_memory.*` stable keys are reserved to the `ic-memory` authority.
260    #[error("stable key '{stable_key}' is reserved to authority '{expected_authority}'")]
261    ReservedStableKeyAuthority {
262        /// Stable key being declared.
263        stable_key: String,
264        /// Required declaring authority.
265        expected_authority: &'static str,
266    },
267    /// Caller-supplied policy rejected the declaration.
268    #[error(transparent)]
269    Custom(P),
270}
271
272///
273/// MemoryResolutionError
274///
275/// Logical placement failed before publishing allocation authority.
276///
277
278#[non_exhaustive]
279#[derive(Debug, thiserror::Error)]
280pub enum MemoryResolutionError {
281    #[error("no eligible free slot for {stable_key} under authority {authority}")]
282    Exhausted {
283        stable_key: crate::StableKey,
284        authority: String,
285    },
286    #[error(transparent)]
287    Range(#[from] crate::MemoryManagerRangeAuthorityError),
288    #[error(transparent)]
289    Registry(#[from] StaticMemoryDeclarationError),
290    #[error(transparent)]
291    Declaration(#[from] crate::DeclarationSnapshotError),
292}