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

  1. Check resource.TryGetAnnotations<IProjectMetadata> before adding; skip if one exists
  2. Ensure the resource is only built through AddProject once
  3. 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

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


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)