microsoft/aspire · error · InvalidOperationException
Resource ' ' carries more than one IProjectMetadata…
Error message
Resource '{projectResource.Name}' carries more than one IProjectMetadata annotation. Project resources must carry exactly one stable project metadata annotation. What it means
TryGetProjectMetadata enumerates all IProjectMetadata annotations on the resource and throws InvalidOperationException if more than one exists. Exactly one stable project metadata annotation is required so launch/build tooling has an unambiguous project path.
Solutions
- Check resource.TryGetAnnotations<IProjectMetadata> before adding; skip if one exists
- Ensure the resource is only built through AddProject once
- Remove duplicate metadata additions from custom extension methods
Example fix
// before
resource.Annotations.Add(new ProjectMetadata { ProjectPath = path }); // may duplicate
// after
if (!resource.TryGetAnnotationsOfType<IProjectMetadata>(out var existing) || existing.Length == 0)
{
resource.Annotations.Add(new ProjectMetadata { ProjectPath = path });
} Defensive patterns
Strategy: validation
Validate before calling
var count = resource.Annotations.OfType<IProjectMetadata>().Count();
if (count > 1) throw new InvalidOperationException("Duplicate IProjectMetadata detected."); Try / catch
try { resource.TryGetProjectMetadata(out var m); } catch (InvalidOperationException) { /* de-duplicate annotations before retry */ } Prevention
- Guard metadata additions with a TryGetAnnotations check
- Build project resources exactly once through AddProject
When it happens
Trigger: A resource ended up with two IProjectMetadata annotations — e.g. calling AddProject-like logic twice, or a custom extension calling AddAnnotation(new ProjectMetadata {...}) when one already exists.
Common situations: Builder extensions that unconditionally add metadata without checking TryGetAnnotations; wrapping a project resource in another builder that re-adds metadata; copy/rebuild logic duplicating annotations.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Resource ' ' does not carry an IProjectMetadata annotation.
- Resource ' ' cannot produce a " " launch configuration…
- Resource ' ' project metadata was replaced after project…
- At least one process command success exit code must be…
- BrowserMessageStrings.BrowserLogsEndpointNotAllocated
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/83a4793fb1ef0fa0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/ApplicationModel/ProjectResourceExtensions.cs:65
internal static IProjectMetadata GetProjectMetadata(this IResource projectResource)
{
if (!projectResource.TryGetProjectMetadata(out var projectMetadata))
{
throw new InvalidOperationException($"Resource '{projectResource.Name}' does not carry an {nameof(IProjectMetadata)} annotation.");
}
return projectMetadata;
}
internal static bool TryGetProjectMetadata(this IResource projectResource, [NotNullWhen(true)] out IProjectMetadata? projectMetadata)
{
ArgumentNullException.ThrowIfNull(projectResource);
projectMetadata = projectResource.Annotations.OfType<IProjectMetadata>().ToArray() switch
{
[] => null,
[var metadata] => metadata,
_ => throw new InvalidOperationException(
$"Resource '{projectResource.Name}' carries more than one {nameof(IProjectMetadata)} annotation. " +
"Project resources must carry exactly one stable project metadata annotation.")
};
if (projectMetadata is null)
{
return false;
}
foreach (var launchDefaults in projectResource.Annotations.OfType<ProjectLaunchDefaultsAnnotation>())
{
launchDefaults.ValidateProjectMetadata(projectResource, projectMetadata);
}
return true;
}
}
View on GitHub (pinned to 25830f84bd)