microsoft/aspire · error · DistributedApplicationException
Unable to read the output of 'cargo metadata' for the Rust…
Error message
Unable to read the output of 'cargo metadata' for the Rust app '{resourceName}'. Cargo returned invalid {ex.GetType().Name} output. What it means
Once 'cargo metadata' exits successfully, ReadAsync passes stdout to CargoMetadata.Parse. If parsing throws any exception other than DistributedApplicationException (e.g. JsonException from malformed JSON), it is wrapped in DistributedApplicationException stating that cargo returned invalid output, preserving the original exception type name.
Solutions
- Run 'cargo metadata --format-version 1' manually in the resource directory and inspect stdout for non-JSON content.
- Remove any cargo shim/wrapper/alias so the real cargo binary is invoked, or make the wrapper pass stdout through untouched.
- Check for hooks or environment (RUSTFLAGS, custom config, plugin scripts) that cause cargo to emit extra stdout.
- Update the Rust toolchain if the installed cargo emits an unexpected metadata schema, then retry.
Example fix
// diagnose non-JSON cargo output // before $ which cargo /usr/local/bin/cargo # a wrapper script printing banners // after $ which cargo ~/.cargo/bin/cargo # real cargo; stdout is pure JSON
Defensive patterns
Strategy: validation
Validate before calling
# Ensure cargo emits clean JSON: cargo metadata --format-version 1 | python -c 'import json,sys; json.load(sys.stdin)' && echo OK
Try / catch
try { /* start Rust resource */ }
catch (DistributedApplicationException ex) when (ex.Message.Contains("Cargo returned invalid"))
{ /* inspect raw cargo stdout for non-JSON content */ } Prevention
- Remove cargo shims/aliases/wrappers that inject output into stdout.
- Verify 'cargo metadata --format-version 1' stdout parses as pure JSON in your environment.
- Avoid tools or hooks that post-process or truncate cargo output on PATH.
When it happens
Trigger: cargo exits 0 but its stdout is not valid/expected 'cargo metadata --format-version 1' JSON — e.g. extra banner text, output written by a wrapper script, truncation, or a shim that prints diagnostics to stdout.
Common situations: A 'cargo' shim/alias on PATH that injects extra output; tooling that mutates cargo behavior (cargo-wrap scripts); output truncated by an intermediary; cargo printing warnings into the redirected stream in an unexpected format.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- Aspire.Hosting.Rust requires Cargo 1.71 or later because…
- 'cargo metadata' failed for the Rust app
- 'cargo metadata' for the Rust app
- Failed to parse package search results.
- Failed to parse project.assets.json
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/ed0eaa3ac204bd2f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Rust/CargoMetadataReader.cs:137
var stdout = await stdoutTask.ConfigureAwait(false);
var stderr = await stderrTask.ConfigureAwait(false);
if (process.ExitCode != 0)
{
var diagnostic = FormatStandardError(stderr, environment, startInfo.Environment);
var diagnosticSuffix = diagnostic.Length > 0 ? $" {diagnostic}" : string.Empty;
throw new DistributedApplicationException(
$"'cargo metadata' failed for the Rust app '{resourceName}' with exit code {process.ExitCode}.{diagnosticSuffix}");
}
try
{
return CargoMetadata.Parse(stdout);
}
catch (Exception ex) when (ex is not DistributedApplicationException)
{
throw new DistributedApplicationException(
$"Unable to read the output of 'cargo metadata' for the Rust app '{resourceName}'. Cargo returned invalid {ex.GetType().Name} output.");
}
}
internal static string FormatStandardError(
string standardError,
IReadOnlyDictionary<string, string> environment,
IEnumerable<KeyValuePair<string, string?>>? inheritedEnvironment = null)
{
// Cargo wrappers and configuration errors can echo values from the resolved resource environment or
// inherited variables such as CARGO_REGISTRY_TOKEN. Resource values are all user-controlled, while
// inherited values are limited to conventional secret-bearing names to preserve useful diagnostics.
// Redact before truncating so a value that crosses the retained-output boundary cannot leak partially.
if (string.IsNullOrWhiteSpace(standardError))
{
return string.Empty;
}
View on GitHub (pinned to 25830f84bd)