Skip to content

Errors

Plugin failures are typed TOVIO errors, not opaque shell failures. Every error carries a stable TVO-PLUGIN-* code, and the failure is structured so an agent can branch on the typed status and the finding codes rather than scraping text (REQ-PLUGIN-076).

The TVO-PLUGIN-* catalog

Code Meaning Typical cause What to do
TVO-PLUGIN-001 Plugin manifest invalid Missing required field, bad type/runtime, malformed id, no integrity metadata and no local-dev marker, or a file that is not valid TOML. Fix the field the reason names, then re-run tovio plugin validate <path>. install validates before it writes, so nothing was stored and there is nothing to undo.
TVO-PLUGIN-002 Plugin not installed / unsupported source A command resolved a plugin id against .tovio/plugins/<id>/ and found nothing — or plugin install could not resolve the source (unsupported scheme or URL shape, TLS/connect/read failure, non-success response, or a response over its streaming size limit). tovio plugin list to see what is installed. Then install from a local package path, or from an HTTPS URL ending in / or /manifest.toml that serves a sibling plugin.wasm.
TVO-PLUGIN-003 Plugin integrity check failed Missing artifact, SHA-256 mismatch, malformed or invalid Ed25519 signature, missing publisher DID, untrusted or revoked publisher, or a malformed trust store. Re-install from a trusted package; tovio plugin trust add did:key:… if you verified the key out of band; rotate to a new key after a revocation; or tovio plugin uninstall <id>. Never treat a mismatch as noise — TOVIO fails closed for a reason.
TVO-PLUGIN-004 Plugin event unsupported Bound to (or run for) an event the manifest does not declare, an unknown event name, or unbind naming a pair with no binding. tovio plugin show <id> lists the events the manifest declares; bind to one of those.
TVO-PLUGIN-005 Plugin capability denied The manifest ∩ binding intersection withheld a capability the operation needed. Widen the binding grant — never beyond the manifest request — or narrow what the plugin needs. A plugin can never grant itself more.
TVO-PLUGIN-006 Plugin sandbox failed (exit class 1, 2 or 13) The artifact is not a valid WASM module or lacks the WASI entry point, the guest imports a network/filesystem/env host function the sandbox does not provide, there is no runtime artifact, run was called on an unbound plugin, or the binary was built without the sandbox. Fix the artifact (valid wasm32-wasi, no forbidden imports), install a package that has one, bind the plugin to the event, or rebuild with --features plugins-wasm. tovio plugin doctor triages the config half.
TVO-PLUGIN-007 Plugin timed out The plugin exceeded timeout_ms and was terminated — by the instruction (fuel) budget or by the wall-clock deadline. Raise timeout_ms in the manifest if the work is legitimately long, or fix a plugin that loops and never terminates. A terminated run has no verdict, so it fails closed.
TVO-PLUGIN-008 Plugin output schema invalid Absent output, non-JSON output, a result claiming a different plugin id or event, a bad schema version, an empty summary, or an empty finding message. For plugin authors: emit the current output schema and reproduce with tovio plugin test. For users: file a plugin bug — TOVIO coerces this to error, so it fails closed on a required operation.
TVO-PLUGIN-009 Required plugin failed An enforcing binding ran its plugin and got fail. This blocks whether or not the binding is required — the gate ran before the operation took effect, so nothing changed. Fix what the plugin flagged, then re-run tovio land / tovio commit. The owner override is to drop the local enforcing binding or re-bind it advisory: tovio plugin unbind <id> --event <event>.
TVO-PLUGIN-010 Required plugin unavailable The required plugin errored, was skipped or reported unsupported, is not installed (a dangling binding), or cannot run because this build has no sandbox. Make it runnable and passing: re-install a missing plugin, fix one that errors, rebuild with --features plugins-wasm, or (owner) drop / re-bind-advisory the binding.
TVO-PLUGIN-011 Protected plaintext denied Execution preflight found the input's redaction policy plaintext-allowed while the effective grant lacks read_protected_plaintext. Refused before any guest code ran. Run the plugin with metadata-only redaction (the default). Protected plaintext access is a deferred, fully-approved opt-in.
TVO-PLUGIN-012 Plugin network denied The effective grant asked for network_access. The sandbox exposes no network host functions at all, so it cannot be honored. Remove the network capability from the binding grant, or use a plugin that does not need the network. Adding network_access will not turn it on.
TVO-PLUGIN-013 Protected plaintext grant refused (exit class 2) tovio plugin bind --grant read_protected_plaintext or tovio policy hook add --grant read_protected_plaintext — that capability needs the full §10 chain, not a flag. Drop read_protected_plaintext from the --grant list. Nothing was written; every other capability, and --grant-read-path, is authored normally.
TVO-PLUGIN-013 Post-event plugin failed (exit class 12) A required enforcing plugin bound to a post-* or conflict-created event reported a failure after the operation was already durable. Address the reported finding as a follow-up change; the operation itself stays. The signed audit chain has already recorded the block. Exit class 12 (POST_EVENT_FAIL).
TVO-PLUGIN-014 Forge enforcing binding refused by org policy (server-side, 422) The served organization plugin allow/deny policy does not permit that plugin id (or its publisher) to back an enforcing gate. A Forge admin has to allow the id in the served plugin-policy document, or the proposal has to use a permitted plugin. A policy that fails to load refuses too, by design — a corrupt policy never degrades to permit-all.
TVO-PLUGIN-015 Landing blocked: no attested passing result (server-side, 422) The required plugin:<id> check is absent, not passing, not authored by a policy-approved attester, or stamped with a stale revision. Get a passing attested result for the proposal's current revision. An amend invalidates a prior plugin attestation exactly as it invalidates approvals, and a conformant runner re-executes.
TVO-PLUGIN-016 Server-side plugin registration refused (server-side, 422) A hosted registration carried unverifiable or local_dev integrity, a sha256 mismatch, an over-cap or non-wasm artifact, or hit an org-policy deny at upload. Register a signed package with verifiable integrity, within the size and wasm-shape caps, whose id the org policy permits.

Two entries share TVO-PLUGIN-013. That is deliberate and documented: TVO-PLUGIN-013 and TVO-PLUGIN-006 are the two named compatibility exceptions whose stable descriptor is keyed by (code, exit_class) rather than by the code alone. 013 carries usage (2) and post-event-failure (12); 006 carries generic (1), usage (2) and permission (13) — the generic one being the lean build with no sandbox compiled in, and the usage one being a config fault such as run on an unbound plugin. For those two codes, read the exit class; never infer a numeric exit from the code alone. Every other TVO-PLUGIN-* code maps to exactly one exit class.

TVO-PLUGIN-013

The post-event half of TVO-PLUGIN-013 is different in kind from TVO-PLUGIN-009 / TVO-PLUGIN-010:

  • Those are pre-event blocks — the operation is refused before it takes effect (exit class 13 / PERM).
  • The post-event TVO-PLUGIN-013 is a diagnostic — the operation (commit, land, …) has already succeeded and is durable. The plugin runs afterward for observability. If a required enforcing binding fails, the CLI returns exit class 12 (POST_EVENT_FAIL) so CI or orchestration can observe it, but the operation itself is not undone.

See Lifecycle events → Post-event semantics for the full rules.

How errors surface

Human output

Every enforcing block is a structured explanation, not a stack trace:

✗ Land blocked by required plugin: com.example.license-check

  A REQUIRED enforcing `pre-land` plugin blocked the land (sandboxed-lifecycle-plugins.md §14/§57,
  REQ-PLUGIN-054/055/065). The operation was gated BEFORE it took effect — nothing changed.

  Plugin:    com.example.license-check v1.2.0
  Binding:   com.example.license-check@pre-land (LOCAL, enforcing, required)
  Result:    fail (enforcing fail)
  Why:       One dependency violates repository license policy.
    [error] Dependency xyz uses a prohibited license. (Cargo.toml)

  This was a LOCAL enforcing binding — not a CI-side or Forge-side gate. Override IS possible for the
  repo owner (this is a local binding, not org policy).

  Fix what the plugin flagged (see the findings above), then re-run `tovio land`
  Or inspect the enforcing binding that required it:
    tovio plugin bindings
  Owner override: drop the local enforcing binding, or re-bind it advisory:
    tovio plugin unbind <plugin-id> --event pre-land

  [TVO-PLUGIN-009]

For a pre-snapshot gate the title reads Snapshot blocked by required plugin: … and the retry guidance points at tovio commit.

JSON output

--json emits the standard TOVIO error envelope — the same shape every command uses, so an agent needs no plugin-specific parser:

{
  "error": {
    "area": "plugin",
    "category": "plugin",
    "code": "TVO-PLUGIN-009",
    "title": "Land blocked by required plugin: com.example.license-check",
    "cause": "A REQUIRED enforcing `pre-land` plugin blocked the land …",
    "context": {},
    "docs": "https://tovio.dev/errors/TVO-PLUGIN-009",
    "exit_class": "permission",
    "exit_code": 13,
    "remediation": [
      { "text": "Fix what the plugin flagged (see the findings above), then re-run `tovio land`" },
      { "text": "Or inspect the enforcing binding that required it", "command": "tovio plugin bindings" }
    ],
    "retryability": "after-user-action"
  }
}

Agents branch on code and on exit_class — the latter matters for TVO-PLUGIN-006 and TVO-PLUGIN-013, whose several meanings are told apart by exit class. The plugin, binding and finding detail rides in cause; where a code carries a machine surface it appears under context (the secret-scan gate, TVO-SECRET-001, puts its findings[] and fingerprints[] there).

Fail-closed on protected operations

For enforcing bindings on protected operations, the following statuses block:

  • fail — always.
  • error, skipped, unsupported — when the binding is required = true.
  • Malformed output — treated as error (TVO-PLUGIN-008).

There is no silent pass. A required plugin that cannot produce a valid pass/warning must stop the operation.

Where a plugin blockage might be safe to override

There is no override flag: tovio land and tovio commit have none. What an owner can do is change the binding that required the plugin — tovio plugin unbind <id> --event <event>, or re-bind it advisory. The block itself is already recorded: an enforcing execution writes signed audit metadata (REQ-PLUGIN-058..060), so the trail exists whether or not you go on to remove the gate.

The one block with a different escape is the default-on secret scanner. Its binding is synthesized rather than stored, so tovio plugin bindings shows nothing to unbind; the error itself names the opt-out (tovio config set secrets.scan off), and on a real terminal tovio commit offers encrypt / block / allow-once instead of hard-blocking. See Secret scanning.

Rules of thumb:

  • Do not work around TVO-PLUGIN-003. Integrity failures indicate tampering or corruption; the artifact is untrustworthy.
  • Do not work around TVO-PLUGIN-011. Protected-content denials are exactly what protected content is for.
  • Re-running after TVO-PLUGIN-007 (timeout) is often reasonable if the plugin is known-good and the workload was unusually large. If it recurs, fix the plugin or raise timeout_ms.
  • Dropping an enforcing binding to get past TVO-PLUGIN-009 deserves a business reason. Removing the gate is a config change, not an audited override — say why in the change that removes it.

Last reviewed September 9, 2026

Suggest an improvement to this page Not for security reports — see disclosure