microsoft/aspire · error · InvalidOperationException
A ConfigureRadiusInfrastructure callback left container
Error message
A ConfigureRadiusInfrastructure callback left container '{container.ContainerMapKey}' with more than one port on {literalPort}/{literalProtocol} (for example port '{portName}'). The Radius container recipe creates one Kubernetes Service port per declared port, so duplicate (containerPort, protocol) pairs would emit conflicting Service ports. Remove the duplicate port. What it means
RadiusInfrastructureBuilder collects every declared (containerPort, protocol) pair per container after callback processing and rejects duplicates. The Radius container recipe creates one Kubernetes Service port per declared port, so two ports on the same containerPort/protocol would emit conflicting Service port entries. The throw prevents generating a broken Service.
Solutions
- Remove the duplicate port entry so each (containerPort, protocol) pair appears at most once per container
- Merge the two named ports into a single port entry with one name
- If two distinct endpoints are needed, give them distinct containerPort values
Example fix
// before
container.Ports["http"] = new() { ContainerPort = 8080, Protocol = "tcp" };
container.Ports["web"] = new() { ContainerPort = 8080, Protocol = "tcp" };
// after
container.Ports["http"] = new() { ContainerPort = 8080, Protocol = "tcp" }; Defensive patterns
Strategy: validation
Validate before calling
var seen = new HashSet<(int, string)>();
foreach (var p in containerPorts)
if (!seen.Add((p.ContainerPort, p.Protocol)))
throw new InvalidOperationException($"Duplicate port {p.ContainerPort}/{p.Protocol}."); Prevention
- Ensure each (containerPort, protocol) pair is unique per container when adding ports in callbacks
- Use distinct containerPort values for distinct endpoints
- Review callback port additions against the ports the resource already declares
When it happens
Trigger: A ConfigureRadiusInfrastructure callback adds or leaves multiple port entries that resolve to the same literal (containerPort, protocol) tuple — detected when seenPorts.Add returns false. Ports skipped by other filters are ignored via 'continue'.
Common situations: Adding a second named port that points at the same containerPort and protocol (e.g. 'http' and 'web' both on 8080/tcp), usually from copy-pasted port declarations in the callback.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- A ConfigureRadiusInfrastructure callback changed port
- A ConfigureRadiusInfrastructure callback replaced port
- A ConfigureRadiusInfrastructure callback replaced the…
- ASPIRERADIUS011
- ASPIRERADIUS046
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/4ef20f76fbe0e19f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs:5050
foreach (var (portName, portValue) in container.Ports)
{
if (portValue.Value is not { } port)
{
continue;
}
// Only literal ports can collide deterministically; non-literal (expression-backed)
// ports on callback-added containers are the customization's own responsibility and
// can't be compared here.
if (((IBicepValue)port.ContainerPort).LiteralValue is not int literalPort ||
((IBicepValue)port.Protocol).LiteralValue is not string literalProtocol)
{
continue;
}
if (!seenPorts.Add((literalPort, literalProtocol)))
{
throw new InvalidOperationException(
$"A ConfigureRadiusInfrastructure callback left container '{container.ContainerMapKey}' with " +
$"more than one port on {literalPort}/{literalProtocol} (for example port '{portName}'). The " +
$"Radius container recipe creates one Kubernetes Service port per declared port, so duplicate " +
$"(containerPort, protocol) pairs would emit conflicting Service ports. Remove the duplicate port.");
}
}
}
ValidateContainerEnvVarForms(options);
}
/// <summary>
/// Rejects a container environment entry that carries neither exactly a <c>value</c> nor a
/// complete <c>valueFrom.secretKeyRef</c>.
/// </summary>
/// <remarks>
/// The Radius container schema models each <c>env</c> entry as one form or the other, and the
/// Kubernetes API server rejects a container env var that carries both <c>value</c> andView on GitHub (pinned to 25830f84bd)