microsoft/aspire · error · InvalidOperationException

Resource ' ' does not carry an IProjectMetadata annotation.

Error message

Resource '{projectResource.Name}' does not carry an IProjectMetadata annotation.

What it means

GetProjectMetadata is the throwing variant of TryGetProjectMetadata: it requires the resource to carry exactly one IProjectMetadata annotation and throws InvalidOperationException naming the resource when none is present.

Solutions

  1. Use TryGetProjectMetadata and handle the false case instead of the throwing overload
  2. Ensure the resource was created via AddProject (which adds IProjectMetadata) before calling GetProjectMetadata
  3. Branch on resource type/annotations before invoking project-only extensions

Example fix

// before
var metadata = resource.GetProjectMetadata();
// after
if (!resource.TryGetProjectMetadata(out var metadata))
{
    return; // not a project resource
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!resource.TryGetProjectMetadata(out var metadata)) return; // or log and skip

Type guard

bool HasProjectMetadata([NotNullWhen(true)] IResource? r) => r is not null && r.TryGetProjectMetadata(out _);

Try / catch

try { var m = resource.GetProjectMetadata(); } catch (InvalidOperationException) { /* handle non-project resource */ }

Prevention

When it happens

Trigger: Calling resource.GetProjectMetadata() on a non-project resource (container, executable, custom resource without project metadata).

Common situations: Generic code that assumes all resources in a collection are projects; calling project-only extension methods on a container resource; a builder misconfigured so the project annotation was never added.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting/ApplicationModel/ProjectResourceExtensions.cs:51

    /// <remarks>
    /// A project resource must carry exactly one <see cref="IProjectMetadata"/> annotation. Project metadata
    /// cannot be replaced after project defaults have been applied because launch settings, endpoints, and
    /// rebuild behavior are derived from that annotation.
    /// </remarks>
    /// <exception cref="InvalidOperationException">Thrown when the project resource doesn't have exactly one project metadata annotation.</exception>
    [AspireExportIgnore(Reason = "Project metadata is a .NET-specific contract and is not part of the ATS surface.")]
    public static IProjectMetadata GetProjectMetadata(this ProjectResource projectResource)
    {
        ArgumentNullException.ThrowIfNull(projectResource);

        return GetProjectMetadata((IResource)projectResource);
    }

    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.")
        };

View on GitHub (pinned to 25830f84bd)