{"record":{"id":"83a4793fb1ef0fa0","repo":"microsoft/aspire","slug":"resource-projectresource-name-carries-more-than-one","errorCode":null,"errorMessage":"Resource '{projectResource.Name}' carries more than one IProjectMetadata annotation. Project resources must carry exactly one stable project metadata annotation.","messagePattern":"Resource '(.+?)' carries more than one IProjectMetadata annotation\\. Project resources must carry exactly one stable project metadata annotation\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/ProjectResourceExtensions.cs","lineNumber":65,"sourceCode":"    internal static IProjectMetadata GetProjectMetadata(this IResource projectResource)\n    {\n        if (!projectResource.TryGetProjectMetadata(out var projectMetadata))\n        {\n            throw new InvalidOperationException($\"Resource '{projectResource.Name}' does not carry an {nameof(IProjectMetadata)} annotation.\");\n        }\n\n        return projectMetadata;\n    }\n\n    internal static bool TryGetProjectMetadata(this IResource projectResource, [NotNullWhen(true)] out IProjectMetadata? projectMetadata)\n    {\n        ArgumentNullException.ThrowIfNull(projectResource);\n\n        projectMetadata = projectResource.Annotations.OfType<IProjectMetadata>().ToArray() switch\n        {\n            [] => null,\n            [var metadata] => metadata,\n            _ => throw new InvalidOperationException(\n                $\"Resource '{projectResource.Name}' carries more than one {nameof(IProjectMetadata)} annotation. \" +\n                \"Project resources must carry exactly one stable project metadata annotation.\")\n        };\n\n        if (projectMetadata is null)\n        {\n            return false;\n        }\n\n        foreach (var launchDefaults in projectResource.Annotations.OfType<ProjectLaunchDefaultsAnnotation>())\n        {\n            launchDefaults.ValidateProjectMetadata(projectResource, projectMetadata);\n        }\n\n        return true;\n    }\n}\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/ProjectResourceExtensions.cs#L47-L83","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nresource.Annotations.Add(new ProjectMetadata { ProjectPath = path }); // may duplicate\n// after\nif (!resource.TryGetAnnotationsOfType<IProjectMetadata>(out var existing) || existing.Length == 0)\n{\n    resource.Annotations.Add(new ProjectMetadata { ProjectPath = path });\n}","handlingStrategy":"validation","validationCode":"var count = resource.Annotations.OfType<IProjectMetadata>().Count();\nif (count > 1) throw new InvalidOperationException(\"Duplicate IProjectMetadata detected.\");","typeGuard":null,"tryCatchPattern":"try { resource.TryGetProjectMetadata(out var m); } catch (InvalidOperationException) { /* de-duplicate annotations before retry */ }","preventionTips":["Guard metadata additions with a TryGetAnnotations check","Build project resources exactly once through AddProject"],"tags":["project-metadata","duplicate-annotation","aspire-hosting"],"backgroundTag":"conflicting-config-options","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}