microsoft/aspire · error · NotSupportedException
HTTP(s) and TCP endpoints cannot be mixed
Error message
HTTP(s) and TCP endpoints cannot be mixed
What it means
Within a single Container App ingress (one target port), all endpoints must be either http/http2 or tcp — they cannot be mixed, since the transport determines the ingress configuration. Aspire groups endpoints by target port and throws this NotSupportedException when a group's transports are incompatible.
Solutions
- Move one of the endpoints to a different target port so each port has a single transport family.
- Unify transports on that port (make both tcp, or both http/http2).
- Remove the redundant endpoint if it duplicates the same listener.
Example fix
// before
.WithHttpEndpoint(port: 8080, name: "http")
.WithEndpoint(targetPort: 8080, name: "raw").WithTransport("tcp");
// after
.WithHttpEndpoint(port: 8080, name: "http")
.WithEndpoint(targetPort: 8081, name: "raw").WithTransport("tcp"); Defensive patterns
Strategy: validation
Validate before calling
var byPort = resource.Annotations.OfType<EndpointAnnotation>()
.GroupBy(a => a.TargetPort ?? a.Port ?? 0)
.Select(g => (Port: g.Key, Transports: g.Select(a => a.Transport ?? "http").Distinct().ToList()));
if (byPort.Any(g => g.Transports is { Count: > 1 } t && t.Contains("tcp") && t.Any(x => x is "http" or "http2")))
throw new InvalidOperationException("Cannot mix http and tcp transports on the same target port."); Type guard
static bool TransportsCompatible(IEnumerable<string> ts) => ts.All(t => t is "http" or "http2") || ts.All(t => t is "tcp");
Try / catch
try { /* build/publish */ } catch (NotSupportedException ex) when (ex.Message == "HTTP(s) and TCP endpoints cannot be mixed") { /* move one endpoint to another port or unify transports */ } Prevention
- Assign each transport family its own target port.
- Keep health/metrics endpoints on separate ports from raw TCP listeners.
- Validate endpoint groupings locally with aspire publish before deploying.
When it happens
Trigger: Two endpoints sharing the same target port where one is tcp and the other is http/http2, e.g., .WithEndpoint(8080, ..., transport: "tcp") together with .WithHttpEndpoint(port: 8080) on the same resource.
Common situations: Adding an HTTP health-check endpoint on the same port as a raw TCP listener; schema-only endpoints (e.g., scheme 'redis' vs 'http') accidentally differing in transport on one port.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Container port is required for all endpoints
- External non-HTTP(s) endpoints are not supported
- Multiple external endpoints are not supported
- The endpoint(s) '"))} specify an unsupported transport. The…
- The property ' ' is not supported for the endpoint ' '.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/d645b2f5deb5b97a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.AppContainers/ContainerAppContext.cs:188
// Multiple external endpoints are not supported
if (endpointsByTargetPort.Count(g => g.External) > 1)
{
throw new NotSupportedException("Multiple external endpoints are not supported");
}
// Any external non-http endpoints are not supported
if (endpointsByTargetPort.Any(g => g.External && !g.IsHttpOnly))
{
throw new NotSupportedException("External non-HTTP(s) endpoints are not supported");
}
// Don't allow mixing http and tcp transports on the same target port
static bool Compatible(string[] transports) =>
transports.All(t => t is "http" or "http2") || transports.All(t => t is "tcp");
if (endpointsByTargetPort.Any(g => !Compatible(g.UniqueTransports)))
{
throw new NotSupportedException("HTTP(s) and TCP endpoints cannot be mixed");
}
// Get all http only groups
var httpOnlyEndpoints = endpointsByTargetPort.Where(g => g.IsHttpOnly).OrderBy(g => g.Index).ToArray();
// Do we only have one?
var httpIngress = httpOnlyEndpoints.Length == 1 ? httpOnlyEndpoints[0] : null;
if (httpIngress is null)
{
// We have more than one, pick prefer external one
var externalHttp = httpOnlyEndpoints.Where(g => g.External).ToArray();
if (externalHttp.Length == 1)
{
httpIngress = externalHttp[0];
}
else if (httpOnlyEndpoints.Length > 0)View on GitHub (pinned to 25830f84bd)