microsoft/aspire · error · ArgumentException

Target endpoint ' ' on resource ' ' has already been added…

Error message

Target endpoint '{targetEndpoint.EndpointName}' on resource '{targetEndpoint.Resource.Name}' has already been added to dev tunnel '{tunnel.Name}'.

What it means

AddDevTunnelPort prevents the same endpoint reference from being added twice to one dev tunnel. It checks the tunnel's existing Ports for a port whose TargetEndpoint equals the given reference and throws ArgumentException naming the 'targetEndpoint' parameter if found. Each endpoint on a resource can only map to one tunnel port per tunnel.

Solutions

  1. Remove the duplicate WithReference call that passes the same endpoint to the tunnel.
  2. If multiple ports are needed, expose distinct EndpointAnnotation endpoints on the target resource and reference each once.
  3. Check the tunnel builder chain for shared helper methods that may already have added the endpoint.

Example fix

// before
var tunnel = builder.AddDevTunnel("t")
    .WithReference(api.GetEndpoint("https"))
    .WithReference(api.GetEndpoint("https")); // duplicate
// after
var tunnel = builder.AddDevTunnel("t")
    .WithReference(api.GetEndpoint("https"));
Defensive patterns

Strategy: validation

Validate before calling

// ensure each endpoint is referenced at most once per tunnel
var seen = new HashSet<string>();
void AddRef(Aspire.Hosting.ApplicationModel.IResourceBuilder<DevTunnelResource> t, Aspire.Hosting.ApplicationModel.EndpointReference e)
{
    if (!seen.Add($"{t.Resource.Name}:{e.EndpointName}:{e.Resource.Name}"))
        throw new InvalidOperationException($"Endpoint {e.EndpointName} already added to tunnel {t.Resource.Name}");
}

Prevention

When it happens

Trigger: Calling WithReference(tunnelBuilder, endpoint) — or chaining WithReference for the same endpoint — more than once against the same tunnel, e.g. WithReference(tunnel, api.GetEndpoint("https")) appearing twice, or an endpoint being routed through multiple WithReference calls.

Common situations: Copy-pasted builder chains adding the same endpoint twice; a shared extension method that also adds the endpoint to a tunnel the user already wired; accidentally passing the same EndpointReference instead of two different endpoints.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/ca350ec94d62e56a. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.DevTunnels/DevTunnelResourceBuilderExtensions.cs:578

                    }
                }
            });

        return builder;
    }

    private static void AddDevTunnelPort(
        IResourceBuilder<DevTunnelResource> tunnelBuilder,
        EndpointReference targetEndpoint,
        DevTunnelPortOptions? portOptions)
    {
        var tunnel = tunnelBuilder.Resource;
        var targetResource = targetEndpoint.Resource;

        if (tunnel.Ports.FirstOrDefault(p => p.TargetEndpoint == targetEndpoint) is { } existingPort)
        {
            // Port already added to the tunnel for this endpoint
            throw new ArgumentException($"Target endpoint '{targetEndpoint.EndpointName}' on resource '{targetEndpoint.Resource.Name}' has already been added to dev tunnel '{tunnel.Name}'.", nameof(targetEndpoint));
        }

        if (targetEndpoint.Resource.Annotations.OfType<EndpointAnnotation>()
            .SingleOrDefault(a => string.Equals(a.Name, targetEndpoint.EndpointName, StringComparisons.EndpointAnnotationName)) is { } targetEndpointAnnotation)
        {
            // The target endpoint already exists so let's ensure it's target is localhost
            if (!EndpointHostHelpers.IsLocalhostOrLocalhostTld(targetEndpointAnnotation.TargetHost))
            {
                // Target endpoint is not localhost so can't be tunneled
                throw new ArgumentException($"Cannot tunnel endpoint '{targetEndpointAnnotation.Name}' with host '{targetEndpointAnnotation.TargetHost}' on resource '{targetResource.Name}' because it is not a localhost endpoint.", nameof(targetEndpoint));
            }
        }

        portOptions ??= new();
        if (portOptions.Protocol is { } proto && proto is not "http" and not "https" and not "auto")
        {
            throw new ArgumentException($"Invalid protocol '{proto}' specified in port options. Supported protocols are 'http', 'https', or 'auto'. Set protocol to null to use the endpoint's scheme.", nameof(portOptions));
        }

View on GitHub (pinned to 25830f84bd)