{"record":{"id":"4ef20f76fbe0e19f","repo":"microsoft/aspire","slug":"a-configureradiusinfrastructure-callback-left-container","errorCode":null,"errorMessage":"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.","messagePattern":"A ConfigureRadiusInfrastructure callback left container '(.+?)' with more than one port on (.+?)/(.+?) \\(for example port '(.+?)'\\)\\. 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\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs","lineNumber":5050,"sourceCode":"            foreach (var (portName, portValue) in container.Ports)\n            {\n                if (portValue.Value is not { } port)\n                {\n                    continue;\n                }\n\n                // Only literal ports can collide deterministically; non-literal (expression-backed)\n                // ports on callback-added containers are the customization's own responsibility and\n                // can't be compared here.\n                if (((IBicepValue)port.ContainerPort).LiteralValue is not int literalPort ||\n                    ((IBicepValue)port.Protocol).LiteralValue is not string literalProtocol)\n                {\n                    continue;\n                }\n\n                if (!seenPorts.Add((literalPort, literalProtocol)))\n                {\n                    throw new InvalidOperationException(\n                        $\"A ConfigureRadiusInfrastructure callback left container '{container.ContainerMapKey}' with \" +\n                        $\"more than one port on {literalPort}/{literalProtocol} (for example port '{portName}'). The \" +\n                        $\"Radius container recipe creates one Kubernetes Service port per declared port, so duplicate \" +\n                        $\"(containerPort, protocol) pairs would emit conflicting Service ports. Remove the duplicate port.\");\n                }\n            }\n        }\n\n        ValidateContainerEnvVarForms(options);\n    }\n\n    /// <summary>\n    /// Rejects a container environment entry that carries neither exactly a <c>value</c> nor a\n    /// complete <c>valueFrom.secretKeyRef</c>.\n    /// </summary>\n    /// <remarks>\n    /// The Radius container schema models each <c>env</c> entry as one form or the other, and the\n    /// Kubernetes API server rejects a container env var that carries both <c>value</c> and","sourceCodeStart":5032,"sourceCodeEnd":5068,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs#L5032-L5068","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\ncontainer.Ports[\"http\"] = new() { ContainerPort = 8080, Protocol = \"tcp\" };\ncontainer.Ports[\"web\"] = new() { ContainerPort = 8080, Protocol = \"tcp\" };\n// after\ncontainer.Ports[\"http\"] = new() { ContainerPort = 8080, Protocol = \"tcp\" };","handlingStrategy":"validation","validationCode":"var seen = new HashSet<(int, string)>();\nforeach (var p in containerPorts)\n    if (!seen.Add((p.ContainerPort, p.Protocol)))\n        throw new InvalidOperationException($\"Duplicate port {p.ContainerPort}/{p.Protocol}.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["radius","publish","port","duplicate","kubernetes"],"backgroundTag":"conflicting-config-options","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"}