microsoft/aspire · error · NotSupportedException

External non-HTTP(s) endpoints are not supported

Error message

External non-HTTP(s) endpoints are not supported

What it means

Container Apps external ingress only supports HTTP(S) traffic. Aspire validates that any endpoint group marked external consists of http/http2 endpoints only; an external tcp endpoint triggers this NotSupportedException. Expose the tcp endpoint internally instead.

Solutions

  1. Set the tcp endpoint to internal (isExternal: false) and access it via service discovery inside the environment.
  2. Remove external exposure and put a suitable public gateway/proxy (HTTP) in front if public TCP is truly required.
  3. Move that workload off Container Apps if public TCP ingress is a hard requirement.

Example fix

// before
.WithEndpoint(6379, e => e.Name = "redis", isExternal: true).WithTransport("tcp");

// after
.WithEndpoint(6379, e => e.Name = "redis", isExternal: false).WithTransport("tcp");
Defensive patterns

Strategy: validation

Validate before calling

var badExternal = resource.GetEndpoints().Where(e => e.Endpoint.IsExternal && e.Endpoint.Transport == "tcp");
if (badExternal.Any()) throw new InvalidOperationException("External tcp endpoints are not supported on Container Apps.");

Type guard

bool IsHttpExternal(EndpointAnnotation a) => !a.IsExternal || a.Transport is "http" or "http2";

Try / catch

try { /* build/publish */ } catch (NotSupportedException ex) when (ex.Message.Contains("External non-HTTP")) { /* make tcp endpoint internal */ }

Prevention

When it happens

Trigger: Publishing a resource to Container Apps with an endpoint marked isExternal: true whose transport is tcp (e.g., a public database or game-server port).

Common situations: Attempting to publicly expose raw TCP services (Redis, databases, custom protocols) through Container Apps ingress; lifting an app model from a platform that allows external TCP (e.g., LoadBalancer Services) onto Container Apps.

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/ee808d6d977160a1. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Azure.AppContainers/ContainerAppContext.cs:179

                IsHttpOnly = g.All(x => x.resolved.Endpoint.Transport is "http" or "http2"),
                AnyH2 = g.Any(x => x.resolved.Endpoint.Transport is "http2"),
                UniqueTransports = g.Select(x => x.resolved.Endpoint.Transport).Distinct().ToArray(),
                Index = g.Min(x => x.index)
            })
            .ToList();

        // Failure cases

        // 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)

View on GitHub (pinned to 25830f84bd)