{"record":{"id":"4660df895552304f","repo":"microsoft/aspire","slug":"a-configureradiusinfrastructure-callback-replaced-container","errorCode":null,"errorMessage":"A ConfigureRadiusInfrastructure callback replaced container '{container.ContainerMapKey}' name with a non-literal Bicep expression. The Aspire Radius publisher derives service discovery from the original container name, so it must stay the literal resource name '{container.ContainerMapKey}' (this is an Aspire limitation, not a Radius schema requirement). Remove the rename to keep the emitted 'services__*' values addressing the deployed Service.","messagePattern":"A ConfigureRadiusInfrastructure callback replaced container '(.+?)' name with a non-literal Bicep expression\\. The Aspire Radius publisher derives service discovery from the original container name, so it must stay the literal resource name '(.+?)' \\(this is an Aspire limitation, not a Radius schema requirement\\)\\. Remove the rename to keep the emitted 'services__\\*' values addressing the deployed Service\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs","lineNumber":5192,"sourceCode":"\n    // Ensures a container's top-level `name:` still equals its `properties.containers` map key. The\n    // default name is a literal (the resource name); a callback that changes it to a mismatched\n    // literal, or replaces it with a non-literal Bicep expression we cannot compare, throws.\n    //\n    // NOTE: this is an *Aspire* service-discovery limitation, not a Radius v2 schema requirement.\n    // Radius itself permits a container resource whose map keys (e.g. `frontend`, `sidecar`) differ\n    // from the top-level name; Aspire derives `services__*` values from the original resource name,\n    // so a rename would make the emitted address diverge from the deployed Service.\n    private static void ValidateContainerNameMatchesMapKey(RadiusContainerConstruct container)\n    {\n        var name = (IBicepValue)container.ContainerName;\n\n        // An expression-backed BicepValue reports a default LiteralValue (null for string), but to\n        // stay consistent with the port guard we treat any non-null Expression as the non-literal\n        // signal.\n        if (name.Expression is not null || name.LiteralValue is not string literalName)\n        {\n            throw new InvalidOperationException(\n                $\"A ConfigureRadiusInfrastructure callback replaced container '{container.ContainerMapKey}' name \" +\n                $\"with a non-literal Bicep expression. The Aspire Radius publisher derives service discovery from \" +\n                $\"the original container name, so it must stay the literal resource name '{container.ContainerMapKey}' \" +\n                $\"(this is an Aspire limitation, not a Radius schema requirement). Remove the rename to keep the \" +\n                $\"emitted 'services__*' values addressing the deployed Service.\");\n        }\n\n        if (!string.Equals(literalName, container.ContainerMapKey, StringComparison.Ordinal))\n        {\n            throw new InvalidOperationException(\n                $\"A ConfigureRadiusInfrastructure callback renamed container '{container.ContainerMapKey}' to \" +\n                $\"'{literalName}'. The Aspire Radius publisher derives service discovery from the original container \" +\n                $\"name, so renaming it makes the emitted 'services__*' values point at a Service that is no longer \" +\n                $\"produced (this is an Aspire limitation, not a Radius schema requirement). Remove the rename to keep \" +\n                $\"cross-container calls working.\");\n        }\n    }\n","sourceCodeStart":5174,"sourceCodeEnd":5210,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs#L5174-L5210","documentation":"This error is thrown by the Aspire Radius publisher when a ConfigureRadiusInfrastructure callback replaces a container's Bicep name with a non-literal Bicep expression (an expression-backed BicepValue instead of a plain string). The publisher derives the emitted 'services__*' service-discovery environment values from the original literal container name, so the name must remain the literal resource name. Aspire throws at publish time to prevent generating broken cross-container discovery values.","triggerScenarios":"Calling WithRadiusInfrastructure/ConfigureRadiusInfrastructure and inside the callback assigning container.ContainerName = new BicepValue<string>(someExpression) or any BicepValue whose Expression is non-null, or whose LiteralValue is not a string (e.g. null literal).","commonSituations":"Developers try to compute the deployed container name dynamically in Bicep (e.g. from parameters, environment variables, or name suffixes) inside a Radius infrastructure customization callback; this breaks Aspire's discovery generation which needs the static literal.","solutions":["Remove the rename of container.ContainerName in the ConfigureRadiusInfrastructure callback so it stays the literal resource name","If a computed name is needed, rename the Aspire resource itself (before publishing) rather than mutating the Bicep name in the callback","Use a literal string BicepValue equal to container.ContainerMapKey if you must reassign it"],"exampleFix":"// before\ncallback(ctx => { ctx.Container.ContainerName = BicepValue.Create($\"{ctx.Container.ContainerName}-suffix\"); });\n// after\ncallback(ctx => { /* keep ContainerName as the literal resource name */ });","handlingStrategy":"validation","validationCode":"if (((IBicepValue)container.ContainerName).Expression is not null || ((IBicepValue)container.ContainerName).LiteralValue is not string)\n    throw new InvalidOperationException(\"Container name must remain a literal string in ConfigureRadiusInfrastructure.\");","typeGuard":"static bool IsLiteralStringName(IBicepValue name) => name.Expression is null && name.LiteralValue is string;","tryCatchPattern":null,"preventionTips":["Never assign expression-backed BicepValue to ContainerName in Radius callbacks","Keep callbacks limited to adding environment/settings, not renaming containers","Write a publish-time test asserting ContainerName stays a literal equal to the resource name"],"tags":["radius","bicep","publish-time","service-discovery"],"backgroundTag":"unsupported-operation","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"}