{"record":{"id":"40659c453fae065a","repo":"microsoft/aspire","slug":"aspireradius056","errorCode":"ASPIRERADIUS056","errorMessage":"Two Radius constructs emit the same Bicep identifier '{identifier}' ({existing} and {description}). Bicep symbolic names share a single flat namespace, so every emitted resource and parameter must have a distinct identifier. Rename the conflicting resource — note that resource names are sanitized to Bicep identifiers (e.g. 'my-x' and 'my.x' both become 'my_x'), and that the publisher reserves the identifiers 'app', 'app_legacy', and 'recipepack' for its synthesized constructs. Diagnostic: ASPIRERADIUS056.","messagePattern":"Two Radius constructs emit the same Bicep identifier '\\{identifier\\}' \\(\\{existing\\} and \\{description\\}\\)\\. Bicep symbolic names share a single flat namespace, so every emitted resource and parameter must have a distinct identifier\\. Rename the conflicting resource — note that resource names are sanitized to Bicep identifiers \\(e\\.g\\. 'my-x' and 'my\\.x' both become 'my_x'\\), and that the publisher reserves the identifiers 'app', 'app_legacy', and 'recipepack' for its synthesized constructs\\. Diagnostic: ASPIRERADIUS056\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/BicepPostProcessor.cs","lineNumber":313,"sourceCode":"        {\n            BicepDictionary<object> nestedObject => nestedObject,\n            BicepList<object> nestedArray => nestedArray,\n            var scalar => new BicepValue<object>(scalar)\n        };\n    }\n\n    private static void ValidateUniqueIdentifiers(RadiusInfrastructureOptions options)\n    {\n        // Maps each claimed Bicep identifier to a human-readable description of the construct that\n        // first claimed it, so the diagnostic can name both sides of a collision. Ordinal because\n        // Bicep identifiers are case-sensitive.\n        var seen = new Dictionary<string, string>(StringComparer.Ordinal);\n\n        void Register(string identifier, string description)\n        {\n            if (seen.TryGetValue(identifier, out var existing))\n            {\n                throw new InvalidOperationException(\n                    $\"Two Radius constructs emit the same Bicep identifier '{identifier}' ({existing} and {description}). \" +\n                    \"Bicep symbolic names share a single flat namespace, so every emitted resource and parameter must \" +\n                    \"have a distinct identifier. Rename the conflicting resource — note that resource names are sanitized \" +\n                    \"to Bicep identifiers (e.g. 'my-x' and 'my.x' both become 'my_x'), and that the publisher reserves the \" +\n                    \"identifiers 'app', 'app_legacy', and 'recipepack' for its synthesized constructs. Diagnostic: ASPIRERADIUS056.\");\n            }\n\n            seen[identifier] = description;\n        }\n\n        // Enumerate every collection added to the flat namespace in CompileBicep, in the same order.\n        foreach (var pack in options.RecipePacks)\n        {\n            Register(pack.BicepIdentifier, \"a recipe pack\");\n        }\n\n        foreach (var environment in options.Environments)\n        {","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/BicepPostProcessor.cs#L295-L331","documentation":"The Radius publisher emits resources and parameters into a single flat Bicep namespace, and ValidateUniqueIdentifiers (called by CompileBicep) throws InvalidOperationException with diagnostic ASPIRERADIUS056 when two constructs sanitize to the same Bicep identifier. Note that names are sanitized (my-x and my.x both become my_x) and 'app', 'app_legacy', and 'recipepack' are reserved by the publisher.","triggerScenarios":"Two Radius resources whose names differ only by characters removed during sanitization (e.g. 'my-x' and 'my.x' → 'my_x'); a user resource named 'app', 'app_legacy', or 'recipepack' colliding with the publisher's synthesized constructs; a resource named identically to an emitted parameter.","commonSituations":"Renaming resources from dashes to dots for different environments while both remain in the model; creating a container literally named 'app'; renaming one of two colliding resources but leaving the other unchanged.","solutions":["Rename one of the conflicting resources so the sanitized identifiers differ (e.g. 'my-x' vs 'my-x2', or use different word separators).","Rename any resource that uses the reserved identifiers 'app', 'app_legacy', or 'recipepack'.","Check the error message's '{existing} and {description}' text to identify exactly which two constructs collide and adjust the one you control.","Verify each emitted resource/parameter name is unique after sanitization by mentally replacing '-', '.', and other non-identifier characters with '_'."],"exampleFix":"// before\nvar a = builder.AddContainer(\"my-x\", \"image\");\nvar b = builder.AddContainer(\"my.x\", \"image\"); // both sanitize to my_x\n// after\nvar a = builder.AddContainer(\"my-x\", \"image\");\nvar b = builder.AddContainer(\"my-x2\", \"image\");","handlingStrategy":"validation","validationCode":"static string SanitizeBicepIdentifier(string name) =>\n    new string(name.Select(c => char.IsLetterOrDigit(c) || c == '_' ? c : '_').ToArray());\nvar reserved = new[] { \"app\", \"app_legacy\", \"recipepack\" };\nvar ids = resources.Select(r => SanitizeBicepIdentifier(r.Name)).ToList();\nif (ids.Distinct().Count() != ids.Count || ids.Any(reserved.Contains))\n    throw new InvalidOperationException(\"Bicep identifier collision or reserved name detected\");","typeGuard":null,"tryCatchPattern":"try { PublishAsRadiusApp(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ASPIRERADIUS056\")) { logger.LogError(ex, \"Duplicate Bicep identifiers in Radius publish\"); throw; }","preventionTips":["Give resources names that remain distinct after sanitization (avoid relying on '-' vs '.' to differ)","Never name resources 'app', 'app_legacy', or 'recipepack'","Run a uniqueness check on sanitized resource names in CI before publishing"],"tags":["bicep","radius","naming-collision","publish"],"backgroundTag":"invalid-identifier","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"}