Skip to main content

meshdb_storage/
error.rs

1use meshdb_core::{EdgeId, NodeId};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum Error {
6    #[error("rocksdb: {0}")]
7    RocksDb(#[from] rocksdb::Error),
8
9    #[error("serialization: {0}")]
10    Serde(#[from] serde_json::Error),
11
12    #[error("core: {0}")]
13    Core(#[from] meshdb_core::Error),
14
15    #[error("missing column family: {0}")]
16    MissingColumnFamily(&'static str),
17
18    #[error("corrupt bytes in {cf}: expected {expected}, got {actual}")]
19    CorruptBytes {
20        cf: &'static str,
21        expected: usize,
22        actual: usize,
23    },
24
25    #[error("node not found: {0}")]
26    NodeNotFound(NodeId),
27
28    #[error("edge not found: {0}")]
29    EdgeNotFound(EdgeId),
30
31    #[error("property {property} of type {kind} is not indexable")]
32    UnindexableValue {
33        property: String,
34        kind: &'static str,
35    },
36
37    /// Two constraint declarations collided on the same name with
38    /// incompatible specs. Raised by `create_property_constraint` when
39    /// `IF NOT EXISTS` is absent and the name is already taken by a
40    /// different `(label, property, kind)`. The resolver is "name wins"
41    /// so the caller can't transparently re-declare under a different
42    /// shape — they have to DROP first.
43    #[error(
44        "a constraint named `{name}` already exists with a different definition; \
45         drop it before re-declaring"
46    )]
47    ConstraintNameConflict { name: String },
48
49    /// `DROP CONSTRAINT` targeted a name that isn't registered and the
50    /// `IF EXISTS` escape wasn't supplied. Callers wrap this for
51    /// user-facing surfaces.
52    #[error("no constraint named `{name}`")]
53    ConstraintNotFound { name: String },
54
55    /// Property-arity mismatch: the caller passed a property list
56    /// whose length is wrong for the constraint kind — e.g. two
57    /// properties to a `UNIQUE` (which accepts exactly one) or an
58    /// empty list to any kind. Surfaced so the Cypher surface can
59    /// give a clear error instead of silently clipping the list.
60    #[error("invalid property arity for {kind}: {details}")]
61    ConstraintArity { kind: String, details: String },
62
63    /// A write would put the store into a state that violates a
64    /// registered constraint. The `kind` field carries the constraint
65    /// type (e.g. `UNIQUE`, `NOT NULL`, `IS :: STRING`) so callers can
66    /// format a clear message. `kind` is `String` rather than
67    /// `&'static str` because `PropertyConstraintKind::PropertyType`
68    /// carries a runtime-selected type name.
69    #[error("constraint `{name}` violated: {kind} on {label}.{property} {details}")]
70    ConstraintViolation {
71        name: String,
72        kind: String,
73        label: String,
74        property: String,
75        details: String,
76    },
77}
78
79pub type Result<T> = std::result::Result<T, Error>;