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

  1. Move one of the endpoints to a different target port so each port has a single transport family.
  2. Unify transports on that port (make both tcp, or both http/http2).
  3. 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

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


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)