ErrLookup › Background articles › eyre::Report: Rust bail!/ensure! errors like 'invalid tool path' and 'git failed with status' explained (mise)

eyre::Report: Rust bail!/ensure! errors like 'invalid tool path' and 'git failed with status' explained (mise)

eyre::Report is the error type Rust programs built on the eyre crate throw with bail! and ensure!, so you meet it as a one-line, self-describing message such as 'invalid tool path ... contains forbidden character' or 'archive does not contain registry entries' whenever an internal guard rejects a value, a download, or an environment before work continues. In mise, the best-documented source of this family, these errors mark shell-safety and path-traversal boundaries, corrupt caches and truncated downloads, stale lockfiles and plans, and platform limits like glibc-only Homebrew bottles. Because every message is written by hand at each call site, the message text itself is the diagnosis: it names the offending value and the expectation it failed.

Distilled from 408 documented records across 2 repositories.

Background

eyre::Report is the interchangeable error type of the eyre crate: Rust programs wrap arbitrary errors in it or, more often, throw it directly with bail!/ensure! at hundreds of discrete guard points. From the caller's side there is no error code and no structured payload to inspect — the report is a formatted prose line with the offending value interpolated directly into it, like 'invalid tool path {s:?}: contains forbidden character {c:?}' or 'cannot relocate {}: replacement for {} does not fit ({} > {} bytes)'. The searchable phrase in the message is the error's identity, which is why one family accumulates hundreds of distinct records (408 documented across two repositories) that all behave the same way at the boundary: the program stops at the guard and prints one sentence.

Most of these guards exist as deliberate fail-fast or security boundaries. mise rejects shell metacharacters (quotes, backtick, backslash, dollar, control characters, and on Windows the cmd.exe metacharacters & | < > ^ %) in tool versions and paths because those strings flow into install directory names and plugin hook command lines; it rejects absolute or parent-escaping bin/rename_exe values so a binary cannot resolve outside the install directory; it sanitizes OCI layer tar entries against .. and drive prefixes as a TarSlip guard; and it refuses an appdir that resolves to the filesystem root because that would silently disable path containment for privileged writes. Resource defenses appear in the same shape: a 16 MiB cap on command-input probe output and a 4096-entry cap on the registry archive as a decompression-bomb defense.

Beyond validation, the family covers integrity and state checks. Downloaded or cached bytes are verified against an expected shape (a registry archive must contain registry/*.toml entries and not more than 4096 of them; a Homebrew bottle must extract to <name>/<version>), git operations re-raise non-zero exits as 'git failed with status' or 'git -C {} {} failed', lockfile-pinned installs refuse tool versions missing from mise.lock, and plan executors abort when a target file changed between confirmation and execution — a deliberate time-of-check/time-of-use guard. Platform contracts round it out: glibc-requiring Homebrew bottles fail on musl distros, and Windows extended-length \\?\ prefixes are rejected because the normalization that rewrites backslashes to '/' cannot apply inside them.

Because each call site authors its own message, wording is library-specific and even guard-specific: the same underlying mistake (a pasted metacharacter, a truncated download) produces different text in different programs, and within one program the same failure can be fatal on one path and downgraded on another — mise turns registry parse failures into a warning with a baked-in fallback in normal startup, and several git query failures are swallowed with .ok(). The depth of documentation in this family comes from mise; when messages differ between the two repositories in the family, treat the phrasing, not the mechanism, as the library-specific part.

Common causes

What usually fixes it

Go deeper

Documented occurrences

…and 388 more across the corpus — use search.

Honest provenance: generated on 2026-08-19 from AI-assisted analysis of the linked records. See how records are made.