1use crate::subnet_catalog::RoutingRange;
2use thiserror::Error as ThisError;
3
4#[derive(Debug, ThisError)]
11pub enum CatalogError {
12 #[error(transparent)]
13 Json(#[from] serde_json::Error),
14
15 #[error("unsupported subnet catalog schema version {found}; supported version is {supported}")]
16 UnsupportedSchemaVersion { found: u32, supported: u32 },
17
18 #[error("subnet catalog network is {actual:?}; expected {expected:?}")]
20 NetworkMismatch {
21 expected: String,
23 actual: String,
25 },
26
27 #[error("subnet catalog Registry canister is {actual}; expected {expected}")]
29 RegistryCanisterMismatch {
30 expected: String,
32 actual: String,
34 },
35
36 #[error("subnet catalog Registry version must be greater than zero")]
38 InvalidRegistryVersion,
39
40 #[error("subnet catalog must contain at least one subnet")]
41 EmptySubnets,
42
43 #[error("subnet catalog must contain at least one routing range")]
44 EmptyRoutingRanges,
45
46 #[error("invalid principal in {field}: {value}: {reason}")]
47 InvalidPrincipal {
48 field: &'static str,
49 value: String,
50 reason: String,
51 },
52
53 #[error("duplicate subnet principal in catalog: {subnet_principal}")]
54 DuplicateSubnet { subnet_principal: String },
55
56 #[error("noncanonical subnet order: {previous} must sort before {current}")]
58 NonCanonicalSubnetOrder {
59 previous: String,
61 current: String,
63 },
64
65 #[error("routing range references unknown subnet: {subnet_principal}")]
66 UnknownRoutingSubnet { subnet_principal: String },
67
68 #[error(
69 "invalid routing range for {subnet_principal}: start {start_canister_id} sorts after end {end_canister_id}"
70 )]
71 InvalidRoutingRange {
72 subnet_principal: String,
73 start_canister_id: String,
74 end_canister_id: String,
75 },
76
77 #[error("overlapping routing ranges: {first} overlaps {second}")]
78 OverlappingRoutingRanges {
79 first: Box<RoutingRange>,
80 second: Box<RoutingRange>,
81 },
82
83 #[error("noncanonical routing range order: {previous} must sort before {current}")]
85 NonCanonicalRoutingOrder {
86 previous: Box<RoutingRange>,
88 current: Box<RoutingRange>,
90 },
91
92 #[error(
94 "subnet {subnet_principal} kind {actual} contradicts Registry subnet_type={registry_subnet_type}; expected {expected}"
95 )]
96 SubnetKindMismatch {
97 subnet_principal: String,
99 registry_subnet_type: i32,
101 expected: String,
103 actual: String,
105 },
106
107 #[error(
109 "subnet {subnet_principal} charges_apply_by_default={actual} contradicts expected {expected}"
110 )]
111 ChargingPolicyMismatch {
112 subnet_principal: String,
114 expected: bool,
116 actual: bool,
118 },
119
120 #[error("subnet {subnet_principal} classification field {field} is invalid: {reason}")]
122 ClassificationMismatch {
123 subnet_principal: String,
125 field: &'static str,
127 reason: String,
129 },
130
131 #[error("invalid catalog timestamp in {field}: {value:?}")]
133 InvalidTimestamp {
134 field: &'static str,
136 value: String,
138 },
139
140 #[error(
142 "catalog timestamp in {field} is in the future: {value}; latest accepted unix time is {latest_allowed_unix_secs}"
143 )]
144 FutureTimestamp {
145 field: &'static str,
147 value: String,
149 latest_allowed_unix_secs: u64,
151 },
152
153 #[error("invalid catalog source endpoint {endpoint:?}: {reason}")]
155 InvalidSourceEndpoint {
156 endpoint: String,
158 reason: String,
160 },
161
162 #[error("invalid catalog provenance field {field}: {reason}")]
164 InvalidProvenance {
165 field: &'static str,
167 reason: String,
169 },
170
171 #[error(
173 "unsupported catalog assurance {assurance}; this build can validate uncertified_query only"
174 )]
175 UnsupportedAssurance {
176 assurance: String,
178 },
179
180 #[error("classification policy schema {found} is unsupported; expected {supported}")]
182 ClassificationPolicyVersionMismatch {
183 found: u32,
185 supported: u32,
187 },
188
189 #[error("classification policy digest mismatch: found {actual}; expected {expected}")]
191 ClassificationPolicyDigestMismatch {
192 expected: String,
194 actual: String,
196 },
197
198 #[error(
200 "resolver policy mismatch: version {actual_version} backend {actual_backend:?}; expected version {expected_version} backend {expected_backend:?}"
201 )]
202 ResolverPolicyMismatch {
203 expected_version: u32,
205 actual_version: u32,
207 expected_backend: String,
209 actual_backend: String,
211 },
212
213 #[error("invalid catalog digest {value:?}; expected 64 lowercase hexadecimal characters")]
215 InvalidCatalogDigest {
216 value: String,
218 },
219
220 #[error("catalog digest mismatch: found {actual}; expected {expected}")]
222 CatalogDigestMismatch {
223 expected: String,
225 actual: String,
227 },
228
229 #[error("subnet principal {subnet_principal} was not found in the cached catalog")]
230 UnknownSubnet { subnet_principal: String },
231
232 #[error("principal prefix {prefix:?} did not match cached subnet principals")]
233 PrincipalPrefixNotFound { prefix: String },
234
235 #[error("principal prefix {prefix:?} is ambiguous; matches: {matches:?}")]
236 AmbiguousPrincipalPrefix {
237 prefix: String,
238 matches: Vec<String>,
239 },
240
241 #[error(
242 "canister principal {canister_principal} was not covered by cached routing ranges at registry_version={registry_version}, catalog_schema_version={catalog_schema_version}"
243 )]
244 RouteNotFound {
245 canister_principal: String,
246 registry_version: u64,
247 catalog_schema_version: u32,
248 },
249}