#[non_exhaustive]pub enum ExecError {
Show 20 variants
VarExpand {
field: &'static str,
source: VarExpandError,
},
InvalidPath(String),
RequireFailed {
detail: String,
},
ExecInvalid(String),
UnknownAction(String),
SymlinkDestOccupied {
dst: PathBuf,
},
SymlinkPrivilegeDenied {
detail: String,
},
PathConflict {
path: PathBuf,
reason: &'static str,
},
RmdirNotEmpty {
path: PathBuf,
},
EnvPersistenceNotSupported {
scope: String,
platform: &'static str,
},
PredicateNotSupported {
predicate: &'static str,
platform: &'static str,
},
PredicateProbeFailed {
predicate: &'static str,
detail: String,
},
EnvPersistenceDenied {
scope: String,
detail: String,
},
ExecNonZero {
status: i32,
command: String,
stderr: String,
},
ExecSpawnFailed {
command: String,
detail: String,
},
FsIo {
op: &'static str,
path: PathBuf,
detail: String,
},
SymlinkAutoKindUnresolvable {
src: PathBuf,
detail: String,
},
MetaCycle {
path: PathBuf,
},
UnknownPackType {
requested: String,
},
SymlinkCreateAfterBackupFailed {
dst: PathBuf,
backup: PathBuf,
create_error: String,
restore_error: Option<String>,
},
}Expand description
Errors surfaced by crate::execute::ActionExecutor::execute
implementations.
Marked #[non_exhaustive] so slice 5b can add wet-run-specific variants
(FsIo, SymlinkCreate, SpawnFailed, ChildExit, …) without
breaking downstream match arms.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
VarExpand
Variable expansion failed on a specific field of an action.
Fields
source: VarExpandErrorUnderlying expansion error.
InvalidPath(String)
An expanded string yielded a path shape grex cannot use (empty, non-UTF-8 surrogate pair, etc.).
RequireFailed
A require action evaluated to false with on_fail: error.
ExecInvalid(String)
An exec action had an internally inconsistent post-expansion shape.
UnknownAction(String)
The executor’s plugin registry has no entry registered under the
action’s name. Emitted by the registry-dispatched
super::FsExecutor / super::PlanExecutor when a caller
constructs them with a partial registry that does not cover every
variant present in the pack.
The stock crate::plugin::Registry::bootstrap path registers all
seven Tier-1 built-ins, so the default super::FsExecutor::new /
super::PlanExecutor::new constructors never surface this variant — it
is only reachable through the explicit with_registry entry points
that accept a custom registry.
SymlinkDestOccupied
A symlink target path is occupied by a non-symlink entry and
backup: false; the wet-run executor refuses to clobber blindly.
SymlinkPrivilegeDenied
Symlink creation returned OS access-denied. On Windows this usually
means Developer Mode is disabled and the caller lacks
SeCreateSymbolicLinkPrivilege.
PathConflict
A filesystem path exists in a shape incompatible with the requested action (e.g. mkdir target is already a regular file).
Fields
RmdirNotEmpty
rmdir without force: true attempted to delete a non-empty dir.
EnvPersistenceNotSupported
An env action requested a persistence scope this platform does not
implement.
PredicateNotSupported
A predicate probed by the predicate evaluator (internal) cannot
be answered on the current platform (e.g. reg_key / psversion
evaluated on non-Windows). Replaces the pre-M4-C conservative-false
stub: planners and wet-run executors now surface the limitation as
a typed error instead of silently lying about satisfiability.
Fields
PredicateProbeFailed
A predicate probe ran on the correct platform but the probe itself
failed in a way that prevents a truthful yes/no answer (e.g. the
powershell.exe child exited non-zero, timed out, or a registry
read returned a non-NOT_FOUND OS error such as ACL denial).
Distinct from ExecError::PredicateNotSupported: that variant
says “grex cannot answer here at all”; this variant says “grex
tried but the probe itself broke”. M4-C post-review introduced it
so syncs fail loud on a broken probe rather than silently
reporting false.
Fields
EnvPersistenceDenied
OS rejected an env-persistence write (e.g. HKLM without admin).
ExecNonZero
An exec action returned a non-zero exit status under
on_fail: error.
stderr contains the captured standard-error stream, truncated to
EXEC_STDERR_CAPTURE_MAX bytes to keep a halt-event log line at
a bounded size. Empty string if the child produced none. PR E
recovery review: previously cmd.status() discarded output, so
debugging non-zero exits was blind.
Fields
stderr: StringCaptured stderr (truncated to EXEC_STDERR_CAPTURE_MAX bytes).
ExecSpawnFailed
An exec action failed to spawn (program not found, permissions, …).
FsIo
Filesystem I/O error attributable to a specific op + path.
Fields
SymlinkAutoKindUnresolvable
Symlink was declared with kind: auto but src does not exist on
disk, so the Windows executor cannot infer whether to call
symlink_file or symlink_dir. The two Win32 syscalls are
distinct and picking the wrong one yields a reparse point the
shell will not resolve.
Pack authors hitting this should set kind: file or
kind: directory explicitly, or ensure src exists before the
action runs (for example via an earlier mkdir). Only surfaced on
Windows; Unix’s single symlink(2) does not require the hint.
Fields
MetaCycle
A meta pack’s recursion re-visited a pack path already active on the dispatch stack.
M5-2c guards crate::plugin::pack_type::MetaPlugin’s registry
dispatch against infinite loops by maintaining a canonicalised
visited-set threaded through crate::execute::ExecCtx. A cycle
implies either an author bug (pack A directly or transitively
includes A) or a registry misconfiguration (a custom pack-type
plugin re-dispatching into its own root). The tree walker performs
its own structural cycle detection at walk time — this variant is
defence-in-depth for the registry-dispatch path, not a replacement.
UnknownPackType
A pack manifest declared a type: value that no crate::plugin::PackTypeRegistry
entry implements. Surfaced by
crate::plugin::pack_type::MetaPlugin when it recurses into a
child whose type is not registered on the outer context’s
crate::execute::ExecCtx::pack_type_registry — the top-level
run_pack_lifecycle guard catches the same shape for the root
pack, but a misconfigured custom registry can still lose an entry
between root and a deep child.
SymlinkCreateAfterBackupFailed
Symlink creation failed after an existing dst was renamed aside
to the backup slot. The original dst no longer exists at the
requested path. Restore attempts also failed, so the backup file is
the only remaining artifact and the user must recover manually.
Surfaced instead of plain ExecError::FsIo so callers can
distinguish “symlink create raced” (dst still present) from the
dangerous “backup orphan” state pinned by the M3 recovery review.
NOTE: Logging backup intent into the event log before the rename is a separate, related gap tracked for PR E (halt-state persistence); this variant covers the in-executor rollback shape only.
Fields
restore_error: Option<String>Some(detail) if the rename-back attempt also failed, else
None. When None, callers should prefer
ExecError::FsIo — this variant only fires when restore
also fails.
Trait Implementations§
Source§impl Error for ExecError
impl Error for ExecError
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 Freeze for ExecError
impl RefUnwindSafe for ExecError
impl Send for ExecError
impl Sync for ExecError
impl Unpin for ExecError
impl UnsafeUnpin for ExecError
impl UnwindSafe for ExecError
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> 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