use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
#[error("id: {0}")]
Id(#[from] IdError),
#[error("codec: {0}")]
Codec(#[from] CodecError),
#[error("store: {0}")]
Store(#[from] StoreError),
#[error("object: {0}")]
Object(#[from] ObjectError),
#[error("repo: {0}")]
Repo(#[from] RepoError),
#[error("sign: {0}")]
Sign(#[from] SignError),
}
pub type Result<T> = core::result::Result<T, Error>;
impl Error {
#[must_use]
pub const fn is_uninitialized(&self) -> bool {
matches!(self, Self::Repo(RepoError::Uninitialized))
}
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum IdError {
#[error("stable id: expected 16 bytes, got {got}")]
StableIdLength {
got: usize,
},
#[error("stable id: not a valid uuid: {source}")]
StableIdParse {
#[source]
source: uuid::Error,
},
#[error("multihash: {source}")]
Multihash {
#[source]
source: multihash::Error,
},
#[error("cid: {source}")]
Cid {
#[source]
source: cid::Error,
},
#[error("link: expected codec 0x{expected:x}, got 0x{got:x}")]
LinkWrongCodec {
expected: u64,
got: u64,
},
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum CodecError {
#[error("encode: {0}")]
Encode(String),
#[error("decode: {0}")]
Decode(String),
#[error("non-canonical form: {0}")]
NonCanonical(String),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum StoreError {
#[error("cid mismatch: claimed {claimed}, computed {computed}")]
CidMismatch {
claimed: crate::id::Cid,
computed: crate::id::Cid,
},
#[error("not found: {cid}")]
NotFound {
cid: crate::id::Cid,
},
#[error("io: {0}")]
Io(String),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SignError {
#[error("no signature attached")]
NoSignature,
#[error("unsupported signature algorithm: {got}")]
WrongAlgorithm {
got: String,
},
#[error("malformed public key")]
MalformedKey,
#[error("malformed signature")]
MalformedSignature,
#[error("signature verification failed")]
InvalidSignature,
#[error("encoding: {0}")]
Encoding(String),
#[error("key revoked at {revoked_at} µs (object time: {time} µs)")]
RevokedKey {
revoked_at: u64,
time: u64,
},
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum RepoError {
#[error("repository not initialized (op-heads store is empty)")]
Uninitialized,
#[error("stale: observed state is no longer current")]
Stale,
#[error("op-DAG has no common ancestor across the current heads")]
NoCommonAncestor,
#[error("query found zero matches")]
NotFound,
#[error("query found multiple matches where exactly one was required")]
AmbiguousMatch,
#[error("index corruption: {context} (cid = {cid})")]
IndexCorrupt {
context: String,
cid: crate::id::Cid,
},
#[error("vector dim mismatch: index dim is {index_dim}, query dim is {query_dim}")]
VectorDimMismatch {
index_dim: u32,
query_dim: usize,
},
#[error(
"retrieve: no filters or rankers configured. \
A text query requires an embedder: \
`mnem config set embed.provider ollama && \
mnem config set embed.model nomic-embed-text` \
(or pass `--where K=V` / `--label L` for a pure filter query)."
)]
RetrievalEmpty,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ObjectError {
#[error("wrong kind: expected '{expected}', got '{got}'")]
WrongKind {
expected: &'static str,
got: String,
},
#[error("embedding size mismatch: expected {expected} bytes, got {got}")]
EmbeddingSizeMismatch {
expected: usize,
got: usize,
},
}