pub enum FullEngineError {
Lean(EngineError),
MemPathNotAllowed {
attempted: PathBuf,
candidate: String,
patterns: Vec<String>,
reason: &'static str,
policy_table: &'static str,
},
InvalidMemName {
name: String,
reason: &'static str,
},
MemReferencedByPolicy {
name: String,
referring_mems: Vec<String>,
},
MemSchemaNotAllowed {
candidate: String,
matched_pattern: String,
requested_schema: String,
allowed_schemas: Vec<String>,
},
ConfigAlreadyExists {
path: PathBuf,
},
MemStorageResidueDetected {
branch_ref: String,
config_blob: Option<String>,
entity_count: usize,
},
}Expand description
Errors surfaced by the full engine extension.
Lean(EngineError) wraps any failure that originates in the
underlying lean engine — full orchestrators that delegate to
memstead_base::Engine propagate lean errors verbatim through this
variant (#[from]), so the wire-rendering layer at the full MCP
surface can recover the lean code() for any wrapped variant.
The remaining variants are lifecycle-only: they fire from the
full mem management orchestrator (create_mem / delete_mem)
and have no lean-side fire conditions. They live in this crate
alongside their orchestrator.
Variants§
Lean(EngineError)
Wrapped lean-engine error. Use this variant whenever a full
code path delegates to memstead_base::Engine and a lean-side
failure should surface unchanged.
MemPathNotAllowed
create_mem / delete_mem rejected because the mem
path is not covered by an allowlist rule. reason is one of
no_allowlist_configured / no_match / outside_workspace.
policy_table names the refusing allowlist —
"mem_management.create" or "mem_management.delete" —
so an agent recovering from the envelope knows which TOML
table to edit without threading subcommand context through
error handling. The two discriminators are orthogonal: reason
names why the gate refused; policy_table names which
gate refused.
Fields
InvalidMemName
create_mem rejected before the allowlist check because the
supplied name is structurally malformed — empty, whitespace,
invalid characters, or carries the reserved __ prefix.
reason discriminates the four shapes so an agent who typed
the wrong thing gets a recoverable signal instead of an
allowlist refusal. Split out of the MemPathNotAllowed (no_match) catch-all so the structural failure modes are
visible.
MemReferencedByPolicy
delete_mem rejected because the workspace
[cross_mem_links] policy grants one or more other mems
permission to write into this one. referring_mems lists the
granting mems sorted alphabetically so the agent can walk
the policy table. The condition is a policy grant, not a
materialised graph edge — revoking the grant in
.memstead/workspace.toml is the recovery path.
MemSchemaNotAllowed
create_mem rejected because the matched create-rule does
not allow the requested schema. allowed_schemas is the
canonicalised allow-list (each entry name@version).
Fields
ConfigAlreadyExists
create_mem rejected because the target .memstead/config.json
already exists at the requested location — the engine never
silently overwrites a prior attempt.
MemStorageResidueDetected
create_mem detected on-disk storage residue for the
requested branch path that is not reflected in the in-memory
mem router — typically left over by a crash or a
partially-failed delete. The caller must select an
explicit recovery action via [MemCreateParams::recovery]
(Reattach, ForceOverwrite, or HardCleanupFirst) and
retry; the special case of unregistered_at-tombstoned
residue (deliberate operator state from memstead mem unregister) defaults to Reattach without this refusal. The
payload carries the composed branch ref, the config-blob path,
and the entity count of the residual data so the caller can
decide between adopting and discarding.
Implementations§
Source§impl FullEngineError
impl FullEngineError
Sourcepub fn prose_render(&self) -> String
pub fn prose_render(&self) -> String
Render rich, fully-inlined recovery prose for the agent-visible
text channel. Closes the asymmetry where structured details.X
fields stayed off the agent’s text channel. Each lifecycle
variant with a structured list (patterns, referring_mems,
allowed_schemas) inlines the full payload; lean wraps
delegate to EngineError::prose_render; trivial variants
fall back to Display.
Sourcepub fn details(&self) -> Value
pub fn details(&self) -> Value
Variant-specific recovery payload, rendered as a structured
JSON object that surfaces under error.details in MCP / CLI
envelopes. The CLI’s mem commands used to discard the engine’s
structured details because the lift code didn’t have a single
source of truth —
this mirrors EngineError::details() so the lift can call
err.details() directly without hand-maintaining each per-
variant payload at the CLI surface.
Lean(inner) delegates to EngineError::details(). Lifecycle
variants return the same JSON object shape full_engine_err_unified
builds on the MCP wire — both surfaces share the payload here
so they cannot drift.
Sourcepub fn code(&self) -> &'static str
pub fn code(&self) -> &'static str
Stable, surface-independent error code token.
Matches memstead_base::EngineError::code() for every variant —
wrapped lean errors delegate to the lean mapping, lifecycle
variants return the exact strings the lean enum returned for
them today. This is load-bearing: the wire-shape pins in
memstead-mcp/tests/wire_shape.rs assert these exact code strings.
Trait Implementations§
Source§impl Debug for FullEngineError
impl Debug for FullEngineError
Source§impl Display for FullEngineError
impl Display for FullEngineError
Source§impl Error for FullEngineError
impl Error for FullEngineError
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()
Source§impl From<EngineError> for FullEngineError
impl From<EngineError> for FullEngineError
Source§fn from(source: EngineError) -> Self
fn from(source: EngineError) -> Self
Auto Trait Implementations§
impl !RefUnwindSafe for FullEngineError
impl !UnwindSafe for FullEngineError
impl Freeze for FullEngineError
impl Send for FullEngineError
impl Sync for FullEngineError
impl Unpin for FullEngineError
impl UnsafeUnpin for FullEngineError
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
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> Fruit for T
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