microsoft/aspire · error · InvalidOperationException
Project defaults have already been applied to resource
Error message
Project defaults have already been applied to resource '{builder.Resource.Name}'. WithProjectDefaults can only be called once per resource, and AddProject, AddCSharpApp and AddDotnetProject already call it. Pass ProjectResourceOptions to the method that adds the resource instead. What it means
WithProjectDefaults throws InvalidOperationException when project launch defaults have already been applied to the resource's metadata. Defaults are deliberately not idempotent, so a second application (detected via TrySetAppliedProjectMetadata returning false) is rejected rather than ignored. AddProject, AddCSharpApp, and AddDotnetProject already call it internally, so calling WithProjectDefaults again — or applying defaults to a resource created another way twice — triggers this error.
Solutions
- Remove the explicit WithProjectDefaults call — AddProject/AddCSharpApp/AddDotnetProject already apply defaults.
- Pass settings via ProjectResourceOptions to the Add* method instead of applying defaults afterwards.
- If using a resource type that does not auto-apply defaults, ensure WithProjectDefaults is called exactly once.
Example fix
// before
var api = builder.AddProject<Projects.Api>("api");
api.WithProjectDefaults(); // throws: defaults already applied
// after
var api = builder.AddProject<Projects.Api>("api", options =>
{
// configure launch settings via ProjectResourceOptions here
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Only call WithProjectDefaults on resources that have not had defaults applied // (i.e. not created via AddProject/AddCSharpApp/AddDotnetProject).
Try / catch
try
{
resourceBuilder.WithProjectDefaults();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Project defaults have already been applied"))
{
logger.LogWarning(ex, "Defaults already applied to {Resource}; skipping.", resourceBuilder.Resource.Name);
} Prevention
- Never call WithProjectDefaults on resources from AddProject/AddCSharpApp/AddDotnetProject.
- Pass configuration via ProjectResourceOptions to the Add* method instead.
- Centralize defaults application in one helper to avoid duplicate calls.
When it happens
Trigger: Explicitly calling WithProjectDefaults on a resource created by AddProject/AddCSharpApp/AddDotnetProject; or calling WithProjectDefaults twice on the same resource.
Common situations: Copy-pasted AppHost code that applies defaults manually after AddProject, migration of older AppHost code to the new defaults API, or shared helper methods that each call WithProjectDefaults.
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
- Launch profile must be a string or ProjectResourceOptions.
- Path to C# project could not be determined. The directory
- -32000
- -32603
- AppHost is incompatible with the CLI. The AppHost must be…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/18622a529cf02b90.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/ProjectResourceBuilderExtensions.cs:514
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(options);
var projectMetadata = builder.Resource.GetProjectMetadata();
// Carries the per-endpoint state the wiring below needs, and marks the resource as
// ".NET-launched" for core features such as the Rebuild command.
if (!builder.Resource.TryGetLastAnnotation<ProjectLaunchDefaultsAnnotation>(out var launchDefaults))
{
launchDefaults = new ProjectLaunchDefaultsAnnotation();
builder.WithAnnotation(launchDefaults);
}
// Applying the defaults twice is rejected rather than ignored because most of the settings and infrastructure
// added below are not idempotent.
if (!launchDefaults.TrySetAppliedProjectMetadata(projectMetadata))
{
throw new InvalidOperationException(
$"Project defaults have already been applied to resource '{builder.Resource.Name}'. " +
$"{nameof(WithProjectDefaults)} can only be called once per resource, and {nameof(AddProject)}, " +
$"{nameof(AddCSharpApp)} and AddDotnetProject already call it. " +
$"Pass {nameof(ProjectResourceOptions)} to the method that adds the resource instead.");
}
launchDefaults.BuildConfiguration =
builder.ApplicationBuilder.AppHostAssembly?.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration;
var launchConfigurationType = ProjectLaunchConfigurationFactory.GetLaunchConfigurationType(
builder.Resource,
projectMetadata);
builder.WithDebugSupport(
mode => ProjectLaunchConfigurationFactory.Create(builder.Resource, mode),
launchConfigurationType);
// File-based apps (a bare .cs file) are a .NET 10 SDK feature. The check lives here rather than in
// each Add* method so every .NET-launched resource gets it, and it is deferred to start time becauseView on GitHub (pinned to 25830f84bd)