Skip to content

DevTunnel resource always reports Unhealthy due to 'devtunnel access list <id> -p <port>' failing to resolve bare tunnel id #18790

Description

Description

The DevTunnel resource created via Aspire.Hosting.DevTunnels is always reported as Unhealthy in the Aspire dashboard, even though the tunnel is actually running correctly and the public URL is reachable and forwards traffic to the referenced resource as expected.

This reproduces both when:

  • an explicit tunnelId is passed to AddDevTunnel(name, tunnelId: "..."), and
  • no tunnelId is passed and Aspire auto-generates one (e.g. shibboleth-tunnel-af080a54), on a tunnel that never previously existed.

So the issue is not related to reusing/naming a pre-existing tunnel.

Root cause (found via manual repro)

DevTunnelHealthCheck calls DevTunnelCliClient.GetAccessAsync(tunnelId, portNumber, ...), which shells out to:

devtunnel access list <tunnelId> -p <portNumber> --json

using the short/bare tunnel id (the one supplied to/generated by AddDevTunnel, without the cluster suffix).

This command call fails:

devtunnel access list shibboleth-tunnel-af080a54 -p 57877 --json
Tunnel service error: Not Found The requested tunnel was not found.

However, the very same bare id works fine for other CLI operations against the same tunnel:

devtunnel show shibboleth-tunnel-af080a54 --json          # OK
devtunnel port show shibboleth-tunnel-af080a54 -p 57877 --json   # OK
devtunnel access list shibboleth-tunnel-af080a54 --json    # OK (no -p)

And it succeeds if the fully cluster-qualified id is used instead:

devtunnel access list shibboleth-tunnel-af080a54.eun1 -p 57877 --json   # OK

So the combination of a bare tunnel id + -p <port> for devtunnel access list appears to fail to resolve the tunnel on the service side, while the same bare id works for every other subcommand (including access list without -p). Because DevTunnelHealthCheck/DevTunnelCliClient.GetAccessAsync always passes the bare id together with the port number, the health check fails on every run, permanently marking the DevTunnel resource (and downstream DevTunnelPort resource) as Unhealthy/Starting, even though the tunnel is fully functional.

Reproduction steps

  1. Create an AppHost with:
    var builder = DistributedApplication.CreateBuilder(args);
    
    var app = builder.AddContainer("app", "some/image", "latest")
        .WithHttpsEndpoint(targetPort: 443, name: "app-https");
    
    var tunnel = builder.AddDevTunnel("app-tunnel")
        .WithAnonymousAccess()
        .WithReference(app);
    
    builder.Build().Run();
  2. aspire start / aspire run.
  3. Wait for the container to become Healthy and the tunnel to finish hosting (Dev tunnel '...' created / Ready to accept connections... in the tunnel resource logs).
  4. Observe in aspire describe (or the dashboard) that the DevTunnel resource stays Unhealthy, with a health report similar to:
    Failed to check dev tunnel '<id>': Failed to get access details for '<id>' port <port>.
    Exit code 1: Tunnel service error: Not Found The requested tunnel was not found.
    
  5. Confirm the tunnel is actually working: curl the public https://<code>-<port>.<cluster>.devtunnels.ms URL — it correctly proxies to the local resource.
  6. Manually reproduce the failing health-check call:
    devtunnel access list <bare-id> -p <port> --json
    
    Note it returns Tunnel service error: Not Found, while devtunnel access list <bare-id>.<cluster> -p <port> --json succeeds.

Expected behavior

The DevTunnel resource should report Healthy once the tunnel is created and hosting connections are established, matching the tunnel's real, working state.

Actual behavior

The DevTunnel resource is permanently Unhealthy, and the associated DevTunnelPort resource never leaves the Starting state, because the health check's devtunnel access list <id> -p <port> CLI call fails to resolve the tunnel when given a non-cluster-qualified id.

Suggested fix

DevTunnelCliClient/DevTunnelHealthCheck could:

  • Use the cluster-qualified tunnel id (as returned by devtunnel create/devtunnel update, e.g. <id>.<cluster>) for subsequent CLI calls that combine an id with -p <port>, instead of the original bare id, or
  • Avoid passing -p to access list when only checking overall tunnel/port reachability, or
  • Fall back to devtunnel port show <id> -p <port> (confirmed working) instead of access list ... -p <port> for the health check.

Versions used

  • Aspire.AppHost.Sdk / Aspire.Hosting.DevTunnels: 13.4.6
  • Aspire CLI: 13.4.6+87fe259e4fc244c599019a7b1304c85a1488f248
  • devtunnel CLI: 1.0.1972+07cc55c789
  • Tunnel service cluster involved: eun1 (devtunnel CLI reports connecting to euw service endpoint, tunnels get provisioned in eun1)
  • OS: Windows
  • TargetFramework: net10.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-integrationsIssues pertaining to Aspire Integrations packages

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions