Skip to main content

newt_interaction/
error.rs

1//! Protocol errors. Fail closed: none of these fall back to guessing.
2
3use thiserror::Error;
4
5/// What can go wrong constructing or reading a protocol record.
6#[derive(Debug, Error)]
7pub enum ProtocolError {
8    /// A canonical encoding or content-id operation failed.
9    #[error("content addressing failed: {0}")]
10    Identity(#[from] content_addressable::ContentError),
11    /// An id was presented in a form that is not its canonical rendering.
12    /// Accepting an alternate spelling would let two strings name one record.
13    #[error("`{presented}` is not the canonical form of this id")]
14    NonCanonicalId {
15        /// What the caller supplied.
16        presented: String,
17    },
18    /// An identifier's shape is invalid (empty, or outside the charset).
19    #[error("invalid {kind}: {reason}")]
20    InvalidId {
21        /// Which identifier kind was rejected.
22        kind: &'static str,
23        /// Why it was rejected.
24        reason: String,
25    },
26    /// A REQUIRED surface feature could not be met — either this build
27    /// does not recognize it, or the surface lacks it. Both are the same
28    /// fact to an operator: the document cannot be shown faithfully.
29    #[error(
30        "cannot present this interaction: it requires `{feature}`{}",
31        if *known { ", which this surface does not provide" }
32        else { ", which this build does not recognize" }
33    )]
34    UnsupportedFeature {
35        /// The feature name, verbatim as the document wrote it.
36        feature: String,
37        /// Whether this build recognizes the name at all.
38        known: bool,
39    },
40    /// The bytes decode, but they are not the canonical encoding of what
41    /// they decode to — reordered map keys, a non-minimal integer, an
42    /// indefinite-length string. Accepting them would mint an id different
43    /// from the one their author published.
44    #[error("non-canonical encoding of {schema} ({input_len} bytes)")]
45    NonCanonical {
46        /// The tag the record declared.
47        schema: String,
48        /// Length of the input.
49        input_len: usize,
50    },
51    /// The bytes are not a readable record. Corruption is a different fact
52    /// from a version we do not know, and is reported differently.
53    #[error("malformed record: {reason}")]
54    Malformed {
55        /// What could not be read.
56        reason: String,
57    },
58    /// A record declared a schema tag this build does not know. Unknown
59    /// REQUIRED behavior fails closed (ADR law 5).
60    #[error("unknown schema tag `{tag}` for {expected}")]
61    UnknownSchema {
62        /// The tag the record carried.
63        tag: String,
64        /// The tag this build understands.
65        expected: &'static str,
66    },
67}