Skip to main content

choreo_content/
error.rs

1//! Structured error type for the Coordination Platform tools.
2//!
3//! Every `execute_*` entry point returns `Result<T, ContentError>`. The daemon
4//! converts this into a tool execution error via
5//! `impl From<ContentError> for ToolExecError`. Production code never panics —
6//! all failures (subxt/interop, IPFS, indexer, protobuf decode, item-id
7//! derivation, account/keystore, config) are surfaced here.
8
9use thiserror::Error;
10
11/// Errors produced by the Choreographr Coordination Platform tools.
12#[derive(Debug, Error)]
13pub enum ContentError {
14    /// The sidecar tokio runtime was never initialized (or failed to start).
15    #[error("coordinator runtime is not initialized")]
16    RuntimeNotInitialized,
17
18    /// Substrate/subxt transport or interop failure.
19    #[error("substrate error: {0}")]
20    Substrate(String),
21
22    /// The transaction was rejected or could not be submitted.
23    #[error("transaction failed: {0}")]
24    Transaction(String),
25
26    /// The account used to sign is missing from the keystore credential store.
27    #[error("unknown polkadot account: {0}")]
28    UnknownAccount(String),
29
30    /// An IPFS operation failed.
31    #[error("ipfs error: {0}")]
32    Ipfs(String),
33
34    /// An image could not be read, decoded, or JPEG-encoded.
35    #[error("image error: {0}")]
36    Image(String),
37
38    /// The indexer WebSocket API request failed.
39    #[error("indexer error: {0}")]
40    Indexer(String),
41
42    /// A content payload could not be encoded/decoded (protobuf) or a field
43    /// was missing/ill-formed.
44    #[error("content error: {0}")]
45    Content(String),
46
47    /// An item ID could not be derived/decoded, or an argument was invalid.
48    #[error("invalid argument: {0}")]
49    InvalidArgument(String),
50
51    /// A CID or sha2-256 digest could not be converted/parsed.
52    #[error("cid error: {0}")]
53    Cid(String),
54
55    /// The keystore/account operation failed.
56    #[error("account error: {0}")]
57    Account(String),
58
59    /// Any other failure (bounded, informational).
60    #[error("content error: {0}")]
61    Other(String),
62}
63
64impl ContentError {
65    /// Convenience constructor for a plain string error.
66    pub fn other(msg: impl Into<String>) -> Self {
67        ContentError::Other(msg.into())
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn messages_render() {
77        assert_eq!(
78            ContentError::RuntimeNotInitialized.to_string(),
79            "coordinator runtime is not initialized"
80        );
81        assert!(
82            ContentError::Substrate("boom".into())
83                .to_string()
84                .contains("boom")
85        );
86        assert!(
87            ContentError::Account("missing".into())
88                .to_string()
89                .contains("missing")
90        );
91    }
92
93    #[test]
94    fn other_constructor() {
95        assert_eq!(ContentError::other("x").to_string(), "content error: x");
96    }
97}