Skip to main content

solid_pod_rs/
error.rs

1//! Crate-wide error type.
2//!
3//! All public APIs return `Result<T, PodError>`.
4
5use thiserror::Error;
6
7/// Errors emitted by solid-pod-rs.
8#[derive(Debug, Error)]
9pub enum PodError {
10    /// The requested resource does not exist (HTTP 404).
11    #[error("resource not found: {0}")]
12    NotFound(String),
13
14    /// A resource already exists at the target path (HTTP 409).
15    #[error("resource already exists: {0}")]
16    AlreadyExists(String),
17
18    /// The authenticated agent lacks the required WAC access mode (HTTP 403).
19    #[error("access forbidden")]
20    Forbidden,
21
22    /// No valid credentials were presented (HTTP 401).
23    #[error("authentication required")]
24    Unauthenticated,
25
26    /// Filesystem or network I/O failure.
27    #[error("I/O error: {0}")]
28    Io(#[from] std::io::Error),
29
30    /// The request path is syntactically invalid or escapes the pod root.
31    #[error("invalid path: {0}")]
32    InvalidPath(String),
33
34    /// The supplied `Content-Type` is not acceptable for this operation.
35    #[error("invalid content type: {0}")]
36    InvalidContentType(String),
37
38    /// JSON serialisation or deserialisation failed.
39    #[error("JSON error: {0}")]
40    Json(#[from] serde_json::Error),
41
42    /// A URL could not be parsed.
43    #[error("URL parse error: {0}")]
44    UrlParse(#[from] url::ParseError),
45
46    /// Base64 decoding failed (e.g. in a NIP-98 or DPoP token).
47    #[error("base64 decode error: {0}")]
48    Base64(#[from] base64::DecodeError),
49
50    /// Hex decoding failed.
51    #[error("hex decode error: {0}")]
52    Hex(#[from] hex::FromHexError),
53
54    /// An ACL document could not be parsed as JSON-LD or Turtle.
55    #[error("ACL parse error: {0}")]
56    AclParse(String),
57
58    /// NIP-98 authentication verification failed.
59    #[error("NIP-98: {0}")]
60    Nip98(String),
61
62    /// The storage watch/notification subsystem encountered an error.
63    #[error("watch subsystem error: {0}")]
64    Watch(String),
65
66    /// A storage backend reported an unclassified error.
67    #[error("backend error: {0}")]
68    Backend(String),
69
70    /// An `If-Match` / `If-None-Match` precondition was not satisfied (HTTP 412).
71    #[error("precondition failed: {0}")]
72    PreconditionFailed(String),
73
74    /// The requested operation is not supported by this configuration.
75    #[error("unsupported: {0}")]
76    Unsupported(String),
77
78    /// The request is malformed (HTTP 400).
79    #[error("bad request: {0}")]
80    BadRequest(String),
81
82    /// Request body exceeds a size limit (HTTP 413 equivalent).
83    ///
84    /// Used by the ACL parsers (`parse_turtle_acl`, `parse_jsonld_acl`) to
85    /// reject oversized documents before parsing begins.
86    #[error("payload too large: {0}")]
87    PayloadTooLarge(String),
88
89    /// Sprint 7: pod-level byte quota exceeded. Wraps the detailed
90    /// [`crate::quota::QuotaExceeded`] struct so consumers can surface
91    /// pod name / used / limit in their HTTP response bodies.
92    #[cfg(feature = "quota")]
93    #[error(transparent)]
94    QuotaExceeded(#[from] crate::quota::QuotaExceeded),
95}
96
97impl From<notify::Error> for PodError {
98    fn from(e: notify::Error) -> Self {
99        PodError::Watch(e.to_string())
100    }
101}