rust-lang/cargo · error
failed to parse process output
Error message
failed to parse process output: {} What it means
process_builder's execute_with_callback captures stdout/stderr; if the callback itself returns an error (callback_error), Cargo wraps it as a ProcessError with the message 'failed to parse process output: {process}'. This indicates the child process ran but its output could not be parsed by the caller-supplied callback.
Solutions
- Capture and inspect the raw stdout/stderr of the failing process to see what could not be parsed.
- Align the parser with the actual tool version/output format.
- Ensure the invoked tool is the expected version and locale (e.g. LC_ALL=C) so output is stable.
- Handle the error in the callback by returning a clearer message or falling back.
Example fix
// before
let output = process.exec_with_streaming(&mut |stdout| parse(stdout), ...)?;
// after
let output = process.exec_with_streaming(&mut |stdout| {
parse(stdout).map_err(|e| format_err!("parse failed for line: {e}"))
}, ...)?; Defensive patterns
Strategy: try-catch
Validate before calling
// Run the process with output captured for diagnostics first
let out = process.output()?;
if !out.status.success() || std::str::from_utf8(&out.stdout).is_err() {
eprintln!("stdout: {:?}", String::from_utf8_lossy(&out.stdout));
} Type guard
null
Try / catch
match process.exec_with_streaming(&mut |s| parse(s), ...) {
Ok(v) => v,
Err(e) => {
// re-run capturing raw output to diagnose parse failure
log::warn!("parse callback failed: {e:#}");
return Err(e);
}
} Prevention
- Pin the external tool version whose output you parse.
- Pin locale (LC_ALL=C) for stable output.
- Log raw stdout/stderr alongside parse errors.
When it happens
Trigger: Invoking an external process via ProcessBuilder with an output-parsing callback that returns Err (e.g. JSON parse failure, unexpected stdout format). The error is propagated with this message.
Common situations: Parsing `rustc --print` / `cargo metadata` / `git` output where the format changed across versions; partial/empty stdout due to process crash; locale-dependent output; version skew between expected and actual tool output.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- argument for argfile contains invalid UTF-8 characters
- argument for argfile contains newlines
- argument for --color must be auto, always, or never, but…
- argument for --color must be auto, always, or never, but…
- artifact-dir was not locked during clean
AI-assisted analysis of rust-lang/cargo@42eee92bc9 (2026-08-11).
Data as JSON: /api/errors/d122257b12b05a5c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cargo-util/src/process_builder.rs:472
}
status
})()
.with_context(|| ProcessError::could_not_execute(self))?;
let output = Output {
status,
stdout,
stderr,
};
{
let to_print = if capture_output { Some(&output) } else { None };
if let Some(e) = callback_error {
let cx = ProcessError::new(
&format!("failed to parse process output: {}", self),
Some(output.status),
to_print,
);
bail!(anyhow::Error::new(cx).context(e));
} else if !output.status.success() {
bail!(ProcessError::new(
&format!("process didn't exit successfully: {}", self),
Some(output.status),
to_print,
));
}
}
Ok(output)
}
/// Builds the command with an `@<path>` argfile that contains all the
/// arguments. This is primarily served for rustc/rustdoc command family.
fn build_command_with_argfile(&self) -> io::Result<(Command, NamedTempFile)> {
use std::io::Write as _;
let mut tmp = tempfile::Builder::new()View on GitHub (pinned to 42eee92bc9)