rust-lang/cargo · error · anyhow::Error

{}: {:?}

Error message

{}: {:?}

What it means

Cache::cached_output captures rustc's stdout as bytes and converts with String::from_utf8; if stdout is not valid UTF-8 it maps the Utf8Error to an anyhow formatting the error and the offending bytes (`{:?}`). The surrounding context notes which rustc command (`{cmd}`) produced the non-UTF-8 output. This typically indicates rustc emitted localized or binary output.

Source

Thrown at src/util/rustc.rs:283

                    dirty: false,
                    data: CacheData::default(),
                }
            }
        }
    }

    fn cached_output(
        &mut self,
        cmd: &ProcessBuilder,
        extra_fingerprint: u64,
    ) -> CargoResult<(String, String)> {
        let key = process_fingerprint(cmd, extra_fingerprint);
        if let std::collections::hash_map::Entry::Vacant(e) = self.data.outputs.entry(key) {
            debug!("rustc info cache miss");
            debug!("running {}", cmd);
            let output = cmd.output()?;
            let stdout = String::from_utf8(output.stdout)
                .map_err(|e| anyhow::anyhow!("{}: {:?}", e, e.as_bytes()))
                .with_context(|| format!("`{}` didn't return utf8 output", cmd))?;
            let stderr = String::from_utf8(output.stderr)
                .map_err(|e| anyhow::anyhow!("{}: {:?}", e, e.as_bytes()))
                .with_context(|| format!("`{}` didn't return utf8 output", cmd))?;
            e.insert(Output {
                success: output.status.success(),
                status: if output.status.success() {
                    String::new()
                } else {
                    cargo_util::exit_status_to_string(output.status)
                },
                code: output.status.code(),
                stdout,
                stderr,
            });
            self.dirty = true;
        } else {
            debug!("rustc info cache hit");

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Set a UTF-8 locale: `export LC_ALL=C.UTF-8` (or `en_US.UTF-8`).
  2. Remove or fix any `RUSTC_WRAPPER` / `build.rustc-wrapper` that writes non-UTF-8 to stdout (wrappers must keep stdout clean for cargo).
  3. Reinstall/repair the toolchain with `rustup toolchain install`.
  4. Run the failing rustc command manually and inspect its raw stdout bytes.

Example fix

# before (wrapper pollutes stdout)
export RUSTC_WRAPPER=./my-wrapper
cargo build

# after (wrapper silent on stdout, or unset)
unset RUSTC_WRAPPER
cargo build
Defensive patterns

Strategy: validation

Validate before calling

use std::process::Command;
fn rustc_stdout_is_utf8(rustc: &str) -> Result<(), String> {
    let out = Command::new(rustc).arg("-vV").output().map_err(|e| e.to_string())?;
    String::from_utf8(out.stdout).map(|_| ()).map_err(|e| format!("rustc stdout not UTF-8: {e}"))
}

Type guard

fn rustc_emits_utf8_stdout(rustc: &str) -> bool {
    std::process::Command::new(rustc).arg("-vV").output()
        .map(|o| std::str::from_utf8(&o.stdout).is_ok()).unwrap_or(false)
}

Try / catch

// Validate wrapper output before letting cargo cache it.
if let Err(e) = String::from_utf8(stdout_bytes.clone()) {
    eprintln!("rustc/wrapper stdout is not UTF-8 ({e}); fix the wrapper or locale");
}

Prevention

When it happens

Trigger: Cargo runs rustc to query info (e.g. `rustc -vV`, `--print`, dep-info) and the rustc process writes non-UTF-8 bytes to stdout — e.g. a locale/localized rustc, a corrupted toolchain, or a custom RUSTC wrapper that emits binary data.

Common situations: A locale/env (`LC_ALL`, `LANG`) causing rustc to emit non-UTF-8 localized text; a misconfigured `RUSTC_WRAPPER`/`build.rustc-wrapper` that pollutes stdout; a broken/corrupt rustc binary; a rustc from a non-standard distribution.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/858c4dd84b4b589b.json. Report an issue: GitHub.