Skip to content

Commit 4c189f4

Browse files
authored
refactor(utils): centralize error handling in shared utils crate (#62)
* refactor(utils): centralize error handling in shared utils crate - Create crates/utils/src/errors.rs with CommonError (expanded), PersonError, ResourceError, GovernanceError — each with From<E> for WasmError - Remove inline error enum definitions from all three coordinator zomes - Re-export error types from nondominium_utils::errors in each zome lib.rs - Fix thiserror version in crates/utils, zome_person, zome_resource to use workspace = true (v2.0), matching workspace declaration - Convert 5 .expect() panics to proper error handling: - 4 link-target conversions in zome_resource changed from .map().expect() to .filter_map() pattern - 1 Option unwrap in capability_based_sharing changed to .ok_or()? Closes #60 * docs(utils): update zome docs to reflect centralized error types
1 parent 928352b commit 4c189f4

16 files changed

Lines changed: 220 additions & 210 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/utils/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ edition = "2021"
66
[dependencies]
77
hdk = { workspace = true }
88
serde = { workspace = true }
9-
thiserror = "1.0"
9+
thiserror = { workspace = true }

crates/utils/src/errors.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use hdk::prelude::*;
2+
3+
// =============================================================================
4+
// CommonError — infrastructure errors shared across all zomes
5+
// =============================================================================
6+
7+
#[derive(Debug, thiserror::Error)]
8+
pub enum CommonError {
9+
#[error("Serialization error: {0}")]
10+
Serialize(String),
11+
#[error("External call failed: {0}")]
12+
External(String),
13+
#[error("Entry not found: {0}")]
14+
EntryNotFound(String),
15+
#[error("Record not found: {0}")]
16+
RecordNotFound(String),
17+
#[error("Link operation failed: {0}")]
18+
LinkError(String),
19+
#[error("Action hash not found: {0}")]
20+
ActionHashNotFound(String),
21+
#[error("Entry operation failed: {0}")]
22+
EntryOperationFailed(String),
23+
}
24+
25+
impl From<CommonError> for WasmError {
26+
fn from(err: CommonError) -> Self {
27+
wasm_error!(WasmErrorInner::Guest(err.to_string()))
28+
}
29+
}
30+
31+
// =============================================================================
32+
// PersonError — domain errors for zome_person
33+
// =============================================================================
34+
35+
#[derive(Debug, thiserror::Error)]
36+
pub enum PersonError {
37+
#[error("Person already exists for this agent")]
38+
PersonAlreadyExists,
39+
40+
#[error("Person not found: {0}")]
41+
PersonNotFound(String),
42+
43+
#[error("Private data not found")]
44+
PrivateDataNotFound,
45+
46+
#[error("Role not found: {0}")]
47+
RoleNotFound(String),
48+
49+
#[error("Not the author of this entry")]
50+
NotAuthor,
51+
52+
#[error("Serialization error: {0}")]
53+
SerializationError(String),
54+
55+
#[error("Entry operation failed: {0}")]
56+
EntryOperationFailed(String),
57+
58+
#[error("Link operation failed: {0}")]
59+
LinkOperationFailed(String),
60+
61+
#[error("Invalid input: {0}")]
62+
InvalidInput(String),
63+
64+
#[error("Insufficient capability level: {0}")]
65+
InsufficientCapability(String),
66+
}
67+
68+
impl From<PersonError> for WasmError {
69+
fn from(err: PersonError) -> Self {
70+
wasm_error!(WasmErrorInner::Guest(err.to_string()))
71+
}
72+
}
73+
74+
// =============================================================================
75+
// ResourceError — domain errors for zome_resource
76+
// =============================================================================
77+
78+
#[derive(Debug, thiserror::Error)]
79+
pub enum ResourceError {
80+
#[error("Resource specification not found: {0}")]
81+
ResourceSpecNotFound(String),
82+
83+
#[error("Economic resource not found: {0}")]
84+
EconomicResourceNotFound(String),
85+
86+
#[error("Governance rule not found: {0}")]
87+
GovernanceRuleNotFound(String),
88+
89+
#[error("Not the author of this entry")]
90+
NotAuthor,
91+
92+
#[error("Not the custodian of this resource")]
93+
NotCustodian,
94+
95+
#[error("Serialization error: {0}")]
96+
SerializationError(String),
97+
98+
#[error("Entry operation failed: {0}")]
99+
EntryOperationFailed(String),
100+
101+
#[error("Link operation failed: {0}")]
102+
LinkOperationFailed(String),
103+
104+
#[error("Invalid input: {0}")]
105+
InvalidInput(String),
106+
107+
#[error("Governance rule violation: {0}")]
108+
GovernanceViolation(String),
109+
}
110+
111+
impl From<ResourceError> for WasmError {
112+
fn from(err: ResourceError) -> Self {
113+
wasm_error!(WasmErrorInner::Guest(err.to_string()))
114+
}
115+
}
116+
117+
// =============================================================================
118+
// GovernanceError — domain errors for zome_gouvernance
119+
// =============================================================================
120+
121+
#[derive(Debug, thiserror::Error)]
122+
pub enum GovernanceError {
123+
#[error("Validation receipt not found: {0}")]
124+
ValidationReceiptNotFound(String),
125+
126+
#[error("Economic event not found: {0}")]
127+
EconomicEventNotFound(String),
128+
129+
#[error("Resource validation not found: {0}")]
130+
ResourceValidationNotFound(String),
131+
132+
#[error("Commitment not found: {0}")]
133+
CommitmentNotFound(String),
134+
135+
#[error("Not authorized for this validation")]
136+
NotAuthorizedValidator,
137+
138+
#[error("Insufficient capability level: {0}")]
139+
InsufficientCapability(String),
140+
141+
#[error("Validation already exists for this item: {0}")]
142+
ValidationAlreadyExists(String),
143+
144+
#[error("Invalid validation scheme: {0}")]
145+
InvalidValidationScheme(String),
146+
147+
#[error("Serialization error: {0}")]
148+
SerializationError(String),
149+
150+
#[error("Entry operation failed: {0}")]
151+
EntryOperationFailed(String),
152+
153+
#[error("Link operation failed: {0}")]
154+
LinkOperationFailed(String),
155+
156+
#[error("Invalid input: {0}")]
157+
InvalidInput(String),
158+
159+
#[error("Cross-zome call failed: {0}")]
160+
CrossZomeCallFailed(String),
161+
}
162+
163+
impl From<GovernanceError> for WasmError {
164+
fn from(err: GovernanceError) -> Self {
165+
wasm_error!(WasmErrorInner::Guest(err.to_string()))
166+
}
167+
}

crates/utils/src/lib.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
use hdk::prelude::*;
22
use serde::{Deserialize, Serialize};
33

4+
pub mod errors;
45
pub mod paths;
56

6-
#[derive(Debug, thiserror::Error)]
7-
pub enum CommonError {
8-
#[error("Serialization error: {0}")]
9-
Serialize(String),
10-
#[error("External call failed: {0}")]
11-
External(String),
12-
}
13-
14-
impl From<CommonError> for WasmError {
15-
fn from(err: CommonError) -> Self {
16-
wasm_error!(WasmErrorInner::Guest(err.to_string()))
17-
}
18-
}
7+
pub use errors::{CommonError, GovernanceError, PersonError, ResourceError};
198

209
/// Utility function for making external local calls to other zomes
2110
/// This follows the pattern established in the Requests & Offers project

dnas/nondominium/zomes/coordinator/zome_gouvernance/src/lib.rs

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use hdk::prelude::*;
2+
pub use nondominium_utils::errors::GovernanceError;
23
use zome_gouvernance_integrity::*;
34

45
pub mod commitment;
@@ -13,54 +14,6 @@ pub use ppr::*;
1314
pub use private_data_validation::*;
1415
pub use validation::*;
1516

16-
#[derive(Debug, thiserror::Error)]
17-
pub enum GovernanceError {
18-
#[error("Validation receipt not found: {0}")]
19-
ValidationReceiptNotFound(String),
20-
21-
#[error("Economic event not found: {0}")]
22-
EconomicEventNotFound(String),
23-
24-
#[error("Resource validation not found: {0}")]
25-
ResourceValidationNotFound(String),
26-
27-
#[error("Commitment not found: {0}")]
28-
CommitmentNotFound(String),
29-
30-
#[error("Not authorized for this validation")]
31-
NotAuthorizedValidator,
32-
33-
#[error("Insufficient capability level: {0}")]
34-
InsufficientCapability(String),
35-
36-
#[error("Validation already exists for this item: {0}")]
37-
ValidationAlreadyExists(String),
38-
39-
#[error("Invalid validation scheme: {0}")]
40-
InvalidValidationScheme(String),
41-
42-
#[error("Serialization error: {0}")]
43-
SerializationError(String),
44-
45-
#[error("Entry operation failed: {0}")]
46-
EntryOperationFailed(String),
47-
48-
#[error("Link operation failed: {0}")]
49-
LinkOperationFailed(String),
50-
51-
#[error("Invalid input: {0}")]
52-
InvalidInput(String),
53-
54-
#[error("Cross-zome call failed: {0}")]
55-
CrossZomeCallFailed(String),
56-
}
57-
58-
impl From<GovernanceError> for WasmError {
59-
fn from(err: GovernanceError) -> Self {
60-
wasm_error!(WasmErrorInner::Guest(err.to_string()))
61-
}
62-
}
63-
6417
#[allow(clippy::large_enum_variant)]
6518
#[derive(Serialize, Deserialize, Debug)]
6619
#[serde(tag = "type")]

dnas/nondominium/zomes/coordinator/zome_person/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ name = "zome_person_coordinator"
1111
hdk = { workspace = true }
1212
serde = { workspace = true }
1313
holochain_serialized_bytes = { workspace = true }
14-
thiserror = "1.0"
14+
thiserror = { workspace = true }
1515
zome_person_integrity = { path = "../../integrity/zome_person" }
1616
nondominium_utils = { path = "../../../../../crates/utils" }

0 commit comments

Comments
 (0)