ic_query/nns/neuron/report/error.rs
1//! Module: nns::neuron::report::error
2//!
3//! Responsibility: expose portable and native-wrapper NNS neuron failures.
4//! Does not own: transport execution, cache mechanics, or process presentation.
5//! Boundary: keeps canister and custom callers independent of native host dependencies.
6
7use crate::nns::governance::NnsGovernanceError;
8#[cfg(feature = "nns-host")]
9use crate::{
10 HostCacheError, nns::governance::NnsGovernanceAttemptReadError, runtime::RuntimeError,
11};
12#[cfg(feature = "nns-host")]
13use std::path::PathBuf;
14use thiserror::Error as ThisError;
15
16///
17/// NnsNeuronError
18///
19/// Portable failure returned while collecting or assembling neuron reports.
20///
21
22#[derive(Debug, ThisError)]
23pub enum NnsNeuronError {
24 /// Shared Governance request, transport, or provenance validation failed.
25 #[error(transparent)]
26 Governance(#[from] NnsGovernanceError),
27
28 /// The requested page size is outside Governance's supported range.
29 #[error("invalid NNS neuron page size {page_size}; expected 1..={max_page_size}")]
30 InvalidPageSize {
31 /// Rejected page size.
32 page_size: u32,
33 /// Largest page supported by Governance.
34 max_page_size: u32,
35 },
36
37 /// Governance returned its typed application-level error.
38 #[error("NNS Governance rejected the neuron query with code {error_type}: {message}")]
39 GovernanceResponse {
40 /// Raw Governance error type.
41 error_type: i32,
42 /// Governance error message.
43 message: String,
44 },
45
46 /// Governance has no publicly readable view for the requested neuron id.
47 #[error("NNS neuron {neuron_id} was not found")]
48 NeuronNotFound {
49 /// Requested neuron identifier.
50 neuron_id: u64,
51 },
52
53 /// Governance returned a neuron row without its required identifier.
54 #[error("NNS Governance returned a neuron row without an id")]
55 MissingNeuronId,
56
57 /// A source page or detail row violated the neuron contract.
58 #[error("invalid NNS neuron response: {reason}")]
59 InvalidResponse {
60 /// Response invariant that failed.
61 reason: String,
62 },
63}
64
65///
66/// NnsNeuronHostError
67///
68/// Native wrapper failure for neuron live calls, caches, and refreshes.
69///
70
71#[cfg(feature = "nns-host")]
72#[derive(Debug, ThisError)]
73pub enum NnsNeuronHostError {
74 /// Portable neuron collection or validation failed.
75 #[error(transparent)]
76 Neuron(#[from] NnsNeuronError),
77
78 /// A capped or stalled refresh stopped before proving API exhaustion.
79 #[error(
80 "NNS neuron refresh stopped after {pages_fetched} pages and {rows_fetched} rows: {reason}"
81 )]
82 IncompleteRefresh {
83 /// Pages retained before the stop.
84 pages_fetched: u32,
85 /// Rows retained before the stop.
86 rows_fetched: usize,
87 /// Completion invariant that failed.
88 reason: String,
89 },
90
91 /// A stored neuron snapshot did not match its cache key.
92 #[error(
93 "cached NNS neuron snapshot identity mismatch at {}: {field} is {actual}, expected {expected}",
94 path.display()
95 )]
96 CacheIdentityMismatch {
97 /// Cache path being validated.
98 path: PathBuf,
99 /// Identity field that did not match.
100 field: &'static str,
101 /// Identity required by the cache key.
102 expected: String,
103 /// Identity stored in the snapshot.
104 actual: String,
105 },
106
107 /// A stored neuron snapshot failed family-specific validation.
108 #[error("invalid NNS neuron cache at {}: {reason}", path.display())]
109 InvalidCache {
110 /// Cache path being validated.
111 path: PathBuf,
112 /// Cache invariant that failed.
113 reason: String,
114 },
115
116 /// A stored refresh-attempt sidecar failed identity or lifecycle validation.
117 #[error("invalid NNS neuron refresh attempt at {}: {reason}", path.display())]
118 InvalidRefreshAttempt {
119 /// Attempt sidecar path being validated.
120 path: PathBuf,
121 /// Attempt invariant that failed.
122 reason: String,
123 },
124
125 /// Shared cache IO or lock handling failed.
126 #[error(transparent)]
127 Cache(#[from] HostCacheError),
128
129 /// The synchronous host runtime could not execute the live query.
130 #[error(transparent)]
131 Runtime(#[from] RuntimeError),
132}
133
134#[cfg(feature = "nns-host")]
135impl From<NnsGovernanceAttemptReadError> for NnsNeuronHostError {
136 fn from(error: NnsGovernanceAttemptReadError) -> Self {
137 match error {
138 NnsGovernanceAttemptReadError::Cache(error) => Self::Cache(error),
139 NnsGovernanceAttemptReadError::Invalid { path, reason } => {
140 Self::InvalidRefreshAttempt { path, reason }
141 }
142 }
143 }
144}