#[non_exhaustive]pub enum UniError {
Show 53 variants
NotFound {
path: PathBuf,
},
Schema {
message: String,
},
Parse {
message: String,
position: Option<usize>,
line: Option<usize>,
column: Option<usize>,
context: Option<String>,
},
Query {
message: String,
query: Option<String>,
},
Transaction {
message: String,
},
TransactionConflict {
message: String,
},
TransactionAlreadyCompleted,
TransactionRollbackOnly,
ReadOnly {
operation: String,
},
LabelNotFound {
label: String,
},
EdgeTypeNotFound {
edge_type: String,
},
PropertyNotFound {
property: String,
entity_type: String,
label: String,
},
IndexNotFound {
index: String,
},
SnapshotNotFound {
snapshot_id: String,
},
MemoryLimitExceeded {
limit_bytes: usize,
},
DatabaseLocked,
Timeout {
timeout_ms: u64,
},
LocyIncomplete {
detail: Box<LocyIncomplete>,
},
Type {
expected: String,
actual: String,
},
Constraint {
message: String,
},
SerializationConflict {
message: String,
},
ConstraintConflict {
message: String,
},
Storage {
message: String,
source: Option<Box<dyn Error + Send + Sync>>,
},
Io(Error),
Internal(Error),
InvalidIdentifier {
name: String,
reason: String,
},
LabelAlreadyExists {
label: String,
},
EdgeTypeAlreadyExists {
edge_type: String,
},
PermissionDenied {
action: String,
},
InvalidArgument {
arg: String,
message: String,
},
WriteContextAlreadyActive {
session_id: String,
hint: &'static str,
},
CommitTimeout {
tx_id: String,
hint: &'static str,
},
LockTimeout {
timeout_ms: u64,
},
TransactionExpired {
tx_id: String,
hint: &'static str,
},
Cancelled,
StaleDerivedFacts {
version_gap: u64,
},
RuleConflict {
rule_name: String,
},
HookRejected {
message: String,
},
TriggerRejected {
trigger: String,
reason: String,
},
AuthenticationFailed {
reason: String,
},
AuthorizationDenied {
reason: String,
},
EphemeralWriteAttempt {
kind: &'static str,
id: u64,
},
ForkNotFound {
name: String,
},
ForkAlreadyExists {
name: String,
},
ForkWritesNotYetSupported,
ForkInUse {
name: String,
holder_count: usize,
},
ForkInflightTx {
name: String,
},
PendingFlushTimeout {
name: String,
},
ForkCorruptRegistry {
message: String,
},
ForkHasChildren {
name: String,
children: Vec<String>,
},
ForkSubtreeInUse {
blockers: Vec<String>,
},
ForkBudgetExceeded {
current: usize,
max: usize,
},
ForkLifecycle {
name: String,
stage: &'static str,
source: Box<dyn Error + Send + Sync>,
},
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
NotFound
Schema
Parse
Fields
Query
Transaction
TransactionConflict
TransactionAlreadyCompleted
TransactionRollbackOnly
A previous statement in this transaction failed, marking it rollback-only.
Once any statement returns an error, the transaction is poisoned: it has
possibly half-applied rows in its private buffer, so it is no longer
committable (Neo4j-style rollback-only semantics). All further statements
and commit() are rejected with this error; only rollback() (or drop)
succeeds, discarding the partial writes. Start a fresh transaction to
retry.
ReadOnly
Operation not supported on read-only database
LabelNotFound
Label not found in schema
EdgeTypeNotFound
Edge type not found in schema
PropertyNotFound
Property not found on node/edge
IndexNotFound
Index not found
SnapshotNotFound
Snapshot not found
MemoryLimitExceeded
Query memory limit exceeded
DatabaseLocked
Timeout
LocyIncomplete
A Locy program stopped before reaching its least fixed point because it
exceeded its wall-clock timeout or its max_iterations cap.
This is the default outcome of an over-budget evaluation: partial results
are not returned silently. The boxed LocyIncomplete carries the
diagnostics (which rules were skipped, which complement rules are now
unsound, how far evaluation got). The partial facts themselves are not
embedded here — to recover them, re-run with allow_partial set, which
returns Ok with the partial result instead of this error.
Fields
detail: Box<LocyIncomplete>Type
Constraint
SerializationConflict
A transaction was aborted at commit because a concurrent transaction committed a conflicting write since this transaction began (optimistic concurrency control). The transaction may be safely retried.
ConstraintConflict
A transaction was aborted at commit because a concurrent transaction committed a row with the same unique key (serializable MERGE). The transaction may be safely retried, which will observe the existing row.
Storage
Io(Error)
Internal(Error)
InvalidIdentifier
LabelAlreadyExists
EdgeTypeAlreadyExists
PermissionDenied
InvalidArgument
WriteContextAlreadyActive
Write context (transaction, bulk writer, or appender) is already active on session.
CommitTimeout
Transaction commit timed out waiting for the global writer lock.
LockTimeout
A FOR UPDATE pessimistic row lock could not be acquired within the
deadline — the holder is another live transaction (contention or a
lock-ordering deadlock). Unlike a plain UniError::Timeout (a slow
operation that would just time out again), this is transient: a fresh
transaction can retry and win the lock once the holder releases it, so
it is classified retriable. See is_retriable.
TransactionExpired
Transaction exceeded its deadline.
Cancelled
Operation was cancelled via a cancellation token.
StaleDerivedFacts
Derived facts are stale relative to the current database version.
RuleConflict
A Locy rule conflict was detected during transaction commit rule promotion.
HookRejected
A session hook rejected the operation.
TriggerRejected
A synchronous trigger returned TriggerOutcome::Reject (or Err)
during a BeforeMutation / BeforeCommit phase, aborting commit.
AuthenticationFailed
Authentication failed (M5i). Raised when
Uni::session_with_credentials cannot find a matching
AuthProvider or the matched provider rejects the credentials.
AuthorizationDenied
An AuthzPolicy::check returned Decision::Deny for the
current principal (M5i).
EphemeralWriteAttempt
A write was attempted against an ephemeral (transient, in-query)
node or edge — i.e. one whose Vid / Eid has the
EPHEMERAL_BIT set. Ephemeral entities are return-only
projections; SET / DELETE / MERGE against them must fail before
they reach storage (M5g / proposal §4.13.1).
Fields
ForkNotFound
Fork with the given name does not exist in the registry.
ForkAlreadyExists
session.fork(name).new_() was called against an existing fork.
ForkWritesNotYetSupported
Phase-1 gate: writes through forked_session.tx() are blocked
until Phase 2 lands. Reads, locy(), and admin paths work.
ForkInUse
Drop refused because forked sessions are still alive on the fork.
ForkInflightTx
Drop refused because a transaction has uncommitted mutations on the fork. Commit or roll back the transaction first, then retry drop.
PendingFlushTimeout
Drop refused because the fork has pending async flushes that did
not drain within UniConfig::drop_fork_drain_timeout. Either retry
later (the streams will eventually complete) or raise the timeout.
ForkCorruptRegistry
Registry on disk is malformed (corrupt JSON, missing required field, etc.).
ForkHasChildren
Drop refused because this fork has nested children. Use
drop_fork_cascade to remove the whole subtree, or drop the
children individually first.
ForkSubtreeInUse
drop_fork_cascade refused because at least one fork in the
subtree has live sessions or in-flight transactions. No branch
has been deleted yet — the cascade is atomic at the validation
step. Resolve the blockers and retry.
ForkBudgetExceeded
Session::fork(name) refused because the configured max_forks
budget is at capacity. Drop existing forks (or wait for the
sweeper to reap expired ones) and retry. Counts include Active,
Pending, and Tombstoned entries.
ForkLifecycle
2PC step on a fork lifecycle operation failed.
stage names the step (registry_pending, create_branch,
registry_active, tombstone, delete_branch, registry_clear,
backend_unsupported, recovery) so recovery and humans can
triage without parsing prose.
Implementations§
Source§impl UniError
impl UniError
Sourcepub fn is_retriable(&self) -> bool
pub fn is_retriable(&self) -> bool
Returns true when retrying the failed operation from scratch may succeed.
Distinguishes transient contention failures — optimistic-concurrency
aborts and lock/commit timeouts, which a fresh transaction can win — from
deterministic failures (bad query, schema or type violation) that would
fail identically on retry. This is the signal
Session::transact_with_retry
uses to decide whether to re-run a transaction closure.
TransactionExpired is deliberately not retriable here: a fresh
transaction gets a new deadline, but the helper treats deadline expiry as
a caller-set budget, not a contention signal. A plain Timeout is
likewise not retriable — re-running the same slow operation would just
time out again; only CommitTimeout (lock contention at the commit point)
and LockTimeout (a contended FOR UPDATE row lock / deadlock) signal
retriable contention.
§Examples
use uni_common::UniError;
assert!(UniError::SerializationConflict { message: "lost update".into() }.is_retriable());
assert!(!UniError::Schema { message: "no such label".into() }.is_retriable());Trait Implementations§
Source§impl Error for UniError
impl Error for UniError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Auto Trait Implementations§
impl !RefUnwindSafe for UniError
impl !UnwindSafe for UniError
impl Freeze for UniError
impl Send for UniError
impl Sync for UniError
impl Unpin for UniError
impl UnsafeUnpin for UniError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more