atproto_identity/errors.rs
1//! # Structured Error Types
2//!
3//! Comprehensive error handling for AT Protocol identity operations using structured error types
4//! with the `thiserror` library. All errors follow the project convention of prefixed error codes
5//! with descriptive messages.
6//!
7//! ## Error Categories
8//!
9//! - **`WebDIDError`**: Errors specific to `did:web` operations including URL conversion and document fetching
10//! - **`ConfigError`**: Configuration and environment variable related errors
11//! - **`ResolveError`**: Handle and DID resolution errors including DNS/HTTP failures and conflicts
12//! - **`PLCDIDError`**: PLC directory communication and document parsing errors
13//!
14//! ## Error Format
15//!
16//! All errors use the standardized format: `error-{domain}-{number} {message}: {details}`
17
18use thiserror::Error;
19
20/// Error types that can occur when working with Web DIDs
21#[derive(Debug, Error)]
22pub enum WebDIDError {
23 /// Occurs when the DID is missing the 'did:web:' prefix
24 #[error("error-atproto-identity-web-1 Invalid DID format: missing 'did:web:' prefix")]
25 InvalidDIDPrefix,
26
27 /// Occurs when the DID is missing a hostname component
28 #[error("error-atproto-identity-web-2 Invalid DID format: missing hostname component")]
29 MissingHostname,
30
31 /// Occurs when the HTTP request to fetch the DID document fails
32 #[error("error-atproto-identity-web-3 HTTP request failed: {url} {error}")]
33 HttpRequestFailed {
34 /// The URL that was requested
35 url: String,
36 /// The underlying HTTP error
37 error: reqwest::Error,
38 },
39
40 /// Occurs when the DID document cannot be parsed from the HTTP response
41 #[error("error-atproto-identity-web-4 Failed to parse DID document: {url} {error}")]
42 DocumentParseFailed {
43 /// The URL that was requested
44 url: String,
45 /// The underlying parse error
46 error: reqwest::Error,
47 },
48}
49
50/// Error types that can occur when working with configuration
51#[derive(Debug, Error)]
52pub enum ConfigError {
53 /// Occurs when a required environment variable is not set
54 #[error("error-atproto-identity-config-1 Required environment variable not found: {name}")]
55 MissingEnvironmentVariable {
56 /// The name of the missing environment variable
57 name: String,
58 },
59
60 /// Occurs when parsing an IP address from nameserver configuration fails
61 #[error("error-atproto-identity-config-2 Unable to parse nameserver IP: {value}")]
62 InvalidNameserverIP {
63 /// The invalid IP address value that could not be parsed
64 value: String,
65 },
66
67 /// Occurs when version information cannot be determined
68 #[error("error-atproto-identity-config-3 Version information not available: GIT_HASH or CARGO_PKG_VERSION must be set")]
69 VersionNotAvailable,
70}
71
72/// Error types that can occur when resolving AT Protocol identities
73#[derive(Debug, Error)]
74pub enum ResolveError {
75 /// Occurs when multiple different DIDs are found via DNS TXT record lookup
76 #[error("error-atproto-identity-resolve-1 Multiple DIDs resolved for method")]
77 MultipleDIDsFound,
78
79 /// Occurs when no DIDs are found via either DNS or HTTP resolution methods
80 #[error("error-atproto-identity-resolve-2 No DIDs resolved for method")]
81 NoDIDsFound,
82
83 /// Occurs when DNS and HTTP resolution return different DIDs for the same handle
84 #[error("error-atproto-identity-resolve-3 Conflicting DIDs found for method")]
85 ConflictingDIDsFound,
86
87 /// Occurs when DNS TXT record lookup fails
88 #[error("error-atproto-identity-resolve-4 DNS resolution failed: {0:?}")]
89 DNSResolutionFailed(hickory_resolver::ResolveError),
90
91 /// Occurs when HTTP request to .well-known/atproto-did endpoint fails
92 #[error("error-atproto-identity-resolve-5 HTTP resolution failed: {0:?}")]
93 HTTPResolutionFailed(reqwest::Error),
94
95 /// Occurs when HTTP response from .well-known/atproto-did doesn't start with "did:"
96 #[error("error-atproto-identity-resolve-6 Invalid HTTP resolution response")]
97 InvalidHTTPResolutionResponse,
98
99 /// Occurs when input cannot be parsed as a valid handle or DID
100 #[error("error-atproto-identity-resolve-7 Invalid input")]
101 InvalidInput,
102}
103
104/// Error types that can occur when working with PLC DIDs
105#[derive(Debug, Error)]
106pub enum PLCDIDError {
107 /// Occurs when the HTTP request to the PLC directory fails
108 #[error("error-atproto-identity-plc-1 HTTP request failed: {url} {error}")]
109 HttpRequestFailed {
110 /// The URL that was requested
111 url: String,
112 /// The underlying HTTP error
113 error: reqwest::Error,
114 },
115
116 /// Occurs when the DID document cannot be parsed from the PLC directory response
117 #[error("error-atproto-identity-plc-2 Failed to parse DID document: {url} {error}")]
118 DocumentParseFailed {
119 /// The URL that was requested
120 url: String,
121 /// The underlying parse error
122 error: reqwest::Error,
123 },
124}
125
126/// Error types that can occur when working with cryptographic keys
127#[derive(Debug, Error)]
128pub enum KeyError {
129 /// Occurs when multibase decoding of a key fails
130 #[error("error-atproto-identity-key-1 Error decoding key: {0:?}")]
131 DecodeError(multibase::Error),
132
133 /// Occurs when a key cannot be identified or is in an invalid format
134 #[error("error-atproto-identity-key-2 Invalid key: {0:?}")]
135 InvalidKey(anyhow::Error),
136
137 /// Occurs when ECDSA signature parsing fails
138 #[error("error-atproto-identity-key-3 Signature parsing failed: {0:?}")]
139 SignatureError(ecdsa::signature::Error),
140
141 /// Occurs when P-256 key operations fail
142 #[error("error-atproto-identity-key-4 P256 Error: {0:?}")]
143 P256Error(p256::ecdsa::Error),
144
145 /// Occurs when K-256 key operations fail
146 #[error("error-atproto-identity-key-5 K256 Error: {0:?}")]
147 K256Error(k256::ecdsa::Error),
148
149 /// Occurs when ECDSA cryptographic operations fail
150 #[error("error-atproto-identity-key-6 ECDSA Error: {0:?}")]
151 ECDSAError(ecdsa::Error),
152
153 /// Occurs when secret key parsing or operations fail
154 #[error("error-atproto-identity-key-7 Secret Key Error: {0:?}")]
155 SecretKeyError(ecdsa::elliptic_curve::Error),
156
157 /// Occurs when attempting to sign content with a public key instead of a private key
158 #[error("error-atproto-identity-key-8 Private key required for signature")]
159 PrivateKeyRequiredForSignature,
160}