microsoft/aspire · error · InvalidOperationException
A ConfigureRadiusInfrastructure callback replaced container
Error message
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. What it means
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.
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
Example fix
// before
callback(ctx => { ctx.Container.ContainerName = BicepValue.Create($"{ctx.Container.ContainerName}-suffix"); });
// after
callback(ctx => { /* keep ContainerName as the literal resource name */ }); Defensive patterns
Strategy: validation
Validate before calling
if (((IBicepValue)container.ContainerName).Expression is not null || ((IBicepValue)container.ContainerName).LiteralValue is not string)
throw new InvalidOperationException("Container name must remain a literal string in ConfigureRadiusInfrastructure."); Type guard
static bool IsLiteralStringName(IBicepValue name) => name.Expression is null && name.LiteralValue is string;
Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- A ConfigureRadiusInfrastructure callback renamed container
- A ConfigureRadiusInfrastructure callback replaced port
- A ConfigureRadiusInfrastructure callback replaced the…
- A ConfigureRadiusInfrastructure callback changed port
- A ConfigureRadiusInfrastructure callback removed or…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/4660df895552304f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs:5192
// Ensures a container's top-level `name:` still equals its `properties.containers` map key. The
// default name is a literal (the resource name); a callback that changes it to a mismatched
// literal, or replaces it with a non-literal Bicep expression we cannot compare, throws.
//
// NOTE: this is an *Aspire* service-discovery limitation, not a Radius v2 schema requirement.
// Radius itself permits a container resource whose map keys (e.g. `frontend`, `sidecar`) differ
// from the top-level name; Aspire derives `services__*` values from the original resource name,
// so a rename would make the emitted address diverge from the deployed Service.
private static void ValidateContainerNameMatchesMapKey(RadiusContainerConstruct container)
{
var name = (IBicepValue)container.ContainerName;
// An expression-backed BicepValue reports a default LiteralValue (null for string), but to
// stay consistent with the port guard we treat any non-null Expression as the non-literal
// signal.
if (name.Expression is not null || name.LiteralValue is not string literalName)
{
throw new InvalidOperationException(
$"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.");
}
if (!string.Equals(literalName, container.ContainerMapKey, StringComparison.Ordinal))
{
throw new InvalidOperationException(
$"A ConfigureRadiusInfrastructure callback renamed container '{container.ContainerMapKey}' to " +
$"'{literalName}'. The Aspire Radius publisher derives service discovery from the original container " +
$"name, so renaming it makes the emitted 'services__*' values point at a Service that is no longer " +
$"produced (this is an Aspire limitation, not a Radius schema requirement). Remove the rename to keep " +
$"cross-container calls working.");
}
}
View on GitHub (pinned to 25830f84bd)