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

  1. Capture and inspect the raw stdout/stderr of the failing process to see what could not be parsed.
  2. Align the parser with the actual tool version/output format.
  3. Ensure the invoked tool is the expected version and locale (e.g. LC_ALL=C) so output is stable.
  4. 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

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

Related errors


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)