microsoft/aspire · error · InvalidOperationException

Cargo arguments for resource

Error message

Cargo arguments for resource '{resource.Name}' have not been resolved yet. The launch tool arguments must be created after the resource's arguments are evaluated.

What it means

AddRustApp registers a WithLaunchToolArgs callback that reads resource.ResolvedCargoArgs. That value is populated by an earlier callback that resolves the resource's parameterized arguments. If the launch-tool callback runs before the resolution callback, ResolvedCargoArgs is still null and this InvalidOperationException is thrown.

Solutions

  1. Ensure any custom callbacks that need cargo args run after argument evaluation (DistributedApplicationEventing / callback registration order).
  2. Do not invoke WithLaunchToolArgs-equivalent producers manually; let DCP drive the normal lifecycle.
  3. If reproducing in a test, call the resource's argument evaluation step before requesting launch tool args.
  4. Upgrade to a version where the ordering bug (if in the library) is fixed and file a repro if it persists.
Defensive patterns

Strategy: try-catch

Validate before calling

// before consuming launch tool args
var resolved = resource.GetType().GetProperty("ResolvedCargoArgs")?.GetValue(resource) as string[];
if (resolved is null) throw new InvalidOperationException("Evaluate resource arguments before requesting launch tool args");

Try / catch

try { BuildLaunchToolArgs(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("have not been resolved yet")) {
    logger.LogError("Ensure argument evaluation runs before launch tool arg creation");
}

Prevention

When it happens

Trigger: The launch tool args factory is invoked out of order — e.g. custom code or a callback ordering change causes WithLaunchToolArgs's lambda to execute before the argument-resolution callback that assigns ResolvedCargoArgs.

Common situations: Customizing the Rust resource with additional callbacks that run launch tool arg creation early; calling APIs that force launch-config generation before argument evaluation; version upgrades that changed callback ordering.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/47d2900a93c11251. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Rust/RustHostingExtensions.cs:111

            .WithRustDefaults()
            .WithCargoArgs(context => AddInitialCargoArgs(resource, builder.ExecutionContext, context.Args))
            .WithArgs(async context =>
            {
                // Resolve the cargo arguments once and record them: the debug launch configuration
                // reuses this list rather than invoking the user's callbacks a second time.
                var cargoArgs = new List<string>();

                foreach (var annotation in resource.Annotations.OfType<RustCargoArgsCallbackAnnotation>())
                {
                    await annotation.Callback(new RustCargoArgsCallbackContext(resource, cargoArgs, context.CancellationToken)).ConfigureAwait(false);
                }

                resource.ResolvedCargoArgs = cargoArgs;
            })
            .WithLaunchToolArgs(context =>
            {
                var cargoArgs = resource.ResolvedCargoArgs
                    ?? throw new InvalidOperationException(
                        $"Cargo arguments for resource '{resource.Name}' have not been resolved yet. " +
                        "The launch tool arguments must be created after the resource's arguments are evaluated.");

                // No validation is performed on these arguments: every value is passed through raw for
                // cargo itself to accept or reject. Nothing here inspects what they contain, so only the
                // WithCargo* options feed the executable-path and Dockerfile resolution — a flag that
                // arrives as a raw string through WithCargoArgs is not parsed back out. Doing so would be
                // a second, subtly-different implementation of cargo's own argument handling that could
                // never be complete, since a WithArgs callback can append arguments after this point.
                context.Args.Add("run");
                foreach (var cargoArg in cargoArgs)
                {
                    context.Args.Add(cargoArg);
                }

                context.Args.Add("--");
            }, ownedByLaunchConfigurationType: "rust")
            .WithVSCodeDebugging()

View on GitHub (pinned to 25830f84bd)