pub enum PluginError {
Show 15 variants
InvalidManifest(String),
NotFound(String),
AlreadyInstalled(String),
Conflict {
kind: &'static str,
name: String,
plugin_id: String,
},
UnsupportedPlatform {
plugin_id: String,
platform: String,
},
NotImplemented(String),
Registration(String),
ArtifactVerificationFailed(String),
BundleVerificationFailed(String),
ChecksumRequired(String),
UntrustedHost(String),
UnsignedOrUntrustedSignature(String),
RedirectRefused(String),
Io(Error),
Json(Error),
}Variants§
InvalidManifest(String)
plugin.json failed structural validation (see
crate::manifest::PluginManifest::validate) — includes bad ids,
bad semver shape, path-traversal attempts, duplicate ids, etc.
NotFound(String)
No installed plugin with this id (uninstall/lookup).
AlreadyInstalled(String)
A plugin with this id is already installed and install was called
with crate::installer::InstallDisposition::FailIfInstalled (the
bamboo plugin install verb). Re-run as an upgrade
(bamboo plugin update / crate::installer::InstallDisposition::Upgrade)
to replace it in place.
Conflict
A capability the plugin declares collides with an existing entry in a
shared store that is NOT owned by this plugin (a user’s own entry, or
another plugin’s). For MCP servers and workflows the install REFUSES
rather than clobbering — an MCP server id / workflow filename is
referenced elsewhere, so silently overwriting (and later deleting on
uninstall) would destroy the user’s entry. kind is a short label
such as "mcp server" or "workflow".
UnsupportedPlatform
The manifest’s platforms gate excludes the current OS.
NotImplemented(String)
A step this foundation crate deliberately leaves for a later agent
(capability-registration wiring — see PLUGIN_PLAN.md). Returned
instead of panicking so a partially-stacked branch fails a request
cleanly rather than crashing the process.
Registration(String)
A capability failed to register/deregister against AppState for a
reason OTHER than an ownership conflict (e.g. config.json couldn’t
be persisted, a network fetch during source-staging failed). Kept
distinct from Self::Conflict (a deliberate REFUSAL, not a
failure) so callers/HTTP status mapping can tell “your plugin
collides with something” apart from “something broke while trying to
register/fetch it”.
ArtifactVerificationFailed(String)
A downloaded artifact’s sha256 did not match the manifest’s declared
hash. Checked BEFORE unpacking (supply-chain: a URL-installed plugin
ships a binary that will be executed) — never surfaced as a generic
Registration/InvalidManifest error so callers can distinguish “the
author’s manifest is malformed” from “the bytes served at that URL do
not match what the manifest promised”.
BundleVerificationFailed(String)
A downloaded URL plugin BUNDLE (the plugin.json or the archive
containing it — whatever the app layer’s URL-source fetch downloads)
did not hash to the caller-supplied expected sha256. Checked BEFORE
any extraction/parsing, so a tampered bundle is never trusted even
partially. Distinct from Self::ArtifactVerificationFailed (which
is pinned by a hash declared INSIDE the manifest — itself only
trustworthy once the bundle carrying it is verified): this is the
root-of-trust check that closes the circular-trust hole where the
manifest’s own artifact hash could be rewritten by whoever tampered
with the bundle.
ChecksumRequired(String)
A URL plugin install/update was requested with neither a sha256 to
verify the downloaded bundle against, nor an explicit
allow_unverified opt-in. This is the secure-by-default refusal: a
URL install must be either checksum-pinned or an explicit,
deliberate risk acceptance — never a silent “download and trust any
tar.gz”. Raised BEFORE the URL is ever fetched (no network access
happens for a refused install).
UntrustedHost(String)
A URL plugin install/update’s host (and path) is not in the
configured plugin_trust.trusted_hosts allowlist, and the request did
not set allow_untrusted_host. This is the SOURCE-authorization
layer (host allowlist) — distinct from Self::BundleVerificationFailed
(integrity) and Self::UnsignedOrUntrustedSignature (publisher
authenticity). Raised BEFORE the URL is ever fetched, same posture as
Self::ChecksumRequired.
UnsignedOrUntrustedSignature(String)
A URL plugin bundle is unsigned, or its .sig sidecar does not verify
against any key in plugin_trust.trusted_keys, and the request did
not set allow_unsigned. This is the PUBLISHER-authenticity layer —
a signature proves who produced the bytes, which a bare sha256 (only
proving WHAT the bytes are) cannot. Raised after the bundle is
downloaded (the signature is verified over the downloaded bytes) but
before anything is extracted/parsed.
RedirectRefused(String)
A URL plugin install whose bytes will NOT be cryptographically
authenticated (no signature required AND no sha256 — the fully
opted-out allow_unsigned && allow_unverified, “host-only trust”
case) was served an HTTP redirect instead of the bytes. In that case
the host allowlist is the SOLE control over where the bytes come
from, and it only vetted the FIRST hop — transparently following the
redirect would let the bytes come from an unvetted host and silently
defeat the allowlist, so redirects are not followed and a redirect
response is refused. A trust/authorization refusal (same 403 family
as Self::UntrustedHost / Self::UnsignedOrUntrustedSignature),
NOT a server error — it tells the caller how to proceed (install from
the canonical/final URL, provide a signature/--sha256, or trust the
redirect target). Does not arise once a signature or checksum is in
play: those authenticate the bytes regardless of which host served
them, so redirects are followed in that case.
Io(Error)
Json(Error)
Trait Implementations§
Source§impl Debug for PluginError
impl Debug for PluginError
Source§impl Display for PluginError
impl Display for PluginError
Source§impl Error for PluginError
impl Error for PluginError
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()