{"record":{"id":"0ff7a22da64c0ccc","repo":"dotnet/aspnetcore","slug":"the-static-asset-property-value-is-already-map","errorCode":null,"errorMessage":"The static asset '{property.Value}' is already mapped to {value.Url}.","messagePattern":"The static asset '(.+?)' is already mapped to (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/ResourceAssetCollection.cs","lineNumber":40,"sourceCode":"\n    /// <summary>\n    /// Initializes a new instance of <see cref=\"ResourceAssetCollection\"/>\n    /// </summary>\n    /// <param name=\"resources\">The list of resources available.</param>\n    public ResourceAssetCollection(IReadOnlyList<ResourceAsset> resources)\n    {\n        var mappings = new Dictionary<string, ResourceAsset>(StringComparer.OrdinalIgnoreCase);\n        var contentSpecificUrls = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        _resources = resources;\n        foreach (var resource in resources)\n        {\n            foreach (var property in resource.Properties ?? [])\n            {\n                if (property.Name.Equals(\"label\", StringComparison.OrdinalIgnoreCase))\n                {\n                    if (mappings.TryGetValue(property.Value, out var value))\n                    {\n                        throw new InvalidOperationException($\"The static asset '{property.Value}' is already mapped to {value.Url}.\");\n                    }\n                    mappings[property.Value] = resource;\n                    contentSpecificUrls.Add(resource.Url);\n                }\n            }\n        }\n\n        _uniqueUrlMappings = mappings.ToFrozenDictionary();\n        _contentSpecificUrls = contentSpecificUrls.ToFrozenSet();\n    }\n\n    /// <summary>\n    /// Gets the unique content-based URL for the specified static asset.\n    /// </summary>\n    /// <param name=\"key\">The asset name.</param>\n    /// <returns>The unique URL if available, the same <paramref name=\"key\"/> if not available.</returns>\n    public string this[string key] => _uniqueUrlMappings.TryGetValue(key, out var value) ? value.Url : key;\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/ResourceAssetCollection.cs#L22-L58","documentation":"Thrown by the ResourceAssetCollection constructor. While indexing resources, it builds a label->asset map; if two distinct ResourceAsset entries declare the same \"label\" property value, the second one collides with the first. Labels must uniquely identify a content-specific URL, so a duplicate is an unrecoverable mapping conflict.","triggerScenarios":"Constructing a ResourceAssetCollection (e.g., from the static-asset manifest produced at build time) where two resources expose Properties with Name==\"label\" and the same Value. Common with customized asset pipelines that emit duplicate fingerprinted labels.","commonSituations":"Two source files producing assets with identical logical labels after a rename/copy; a build manifest generated twice and concatenated; a manual/incorrect ResourceAsset list passed to a test or service registration.","solutions":["Inspect the ResourceAsset list for duplicate \"label\" property values before constructing the collection.","Regenerate the static-asset manifest (rebuild) so labels are unique.","Dedupe the source list, keeping one ResourceAsset per label, or rename the conflicting labels."],"exampleFix":"// before\nvar assets = new[] {\n    new ResourceAsset(\"/a.file\", new[]{ new ResourceAssetProperty(\"label\", \"logo\") }),\n    new ResourceAsset(\"/b.file\", new[]{ new ResourceAssetProperty(\"label\", \"logo\") }), // dup\n};\nvar col = new ResourceAssetCollection(assets);\n\n// after\nvar byLabel = assets\n    .SelectMany(a => (a.Properties ?? Array.Empty<ResourceAssetProperty>())\n        .Where(p => p.Name.Equals(\"label\", StringComparison.OrdinalIgnoreCase))\n        .Select(p => (p.Value, a)))\n    .GroupBy(x => x.Value, StringComparer.OrdinalIgnoreCase);\nforeach (var g in byLabel) if (g.Count() > 1) throw new InvalidOperationException($\"dup label {g.Key}\");\nvar col = new ResourceAssetCollection(assets);","handlingStrategy":"validation","validationCode":"// Validate the resource list for duplicate labels before constructing the collection.\nstatic bool HasDuplicateLabels(IReadOnlyList<ResourceAsset> assets) {\n    var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n    foreach (var a in assets)\n        foreach (var p in a.Properties ?? Array.Empty<ResourceAssetProperty>())\n            if (p.Name.Equals(\"label\", StringComparison.OrdinalIgnoreCase)\n                && !seen.Add(p.Value)) return true;\n    return false;\n}","typeGuard":null,"tryCatchPattern":"try { _assets = new ResourceAssetCollection(list); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already mapped\")) {\n    _logger.LogError(ex, \"Static asset manifest has duplicate labels; regenerating build output.\");\n    _assets = ResourceAssetCollection.Empty; // fallback only if appropriate\n}","preventionTips":["Regenerate the static-asset manifest when source assets change so labels stay unique.","Run a duplicate-label check over your ResourceAsset list in a startup/test step.","Avoid manually merging two asset manifests; rebuild from a single source."],"tags":["blazor","static-assets","resourceasset","duplicate","configuration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}