microsoft/aspire · error · InvalidOperationException

Tracked browser host does not expose a WebSocket debug…

Error message

Tracked browser host does not expose a WebSocket debug endpoint.

What it means

BrowserHost.CreateCdpConnectionAsync opens a Chrome DevTools Protocol WebSocket connection using the host's DebugEndpoint. This error is thrown when DebugEndpoint is null, meaning the tracked browser host never discovered (or lost) its WebSocket debugger URL, so no CDP connection can be established. It is an upfront invariant check before ConnectAsync.

Solutions

  1. Retry after a short delay: the browser may not have exposed the DevTools WebSocket endpoint yet at connect time.
  2. Verify the browser launch flags include remote debugging (--remote-debugging-port) and the build supports DevTools.
  3. Check the browser process is still alive and healthy; restart the tracked browser if it crashed.
  4. Re-run endpoint discovery (/json/version) to repopulate DebugEndpoint before connecting.

Example fix

// before
var conn = await host.CreateCdpConnectionAsync(handler, logger, ct); // may throw when DebugEndpoint null

// after: guard in caller
if (host.DebugEndpoint is null)
{
    await Task.Delay(500, ct);
    await host.RefreshDiscoveryAsync(ct); // re-probe /json/version
}
var conn = await host.CreateCdpConnectionAsync(handler, logger, ct);
Defensive patterns

Strategy: retry

Validate before calling

if (host.DebugEndpoint is null)
    throw new InvalidOperationException("Browser debug endpoint not discovered yet; wait or re-probe before connecting.");

Type guard

var ready = host is { DebugEndpoint: not null };

Try / catch

try { await host.CreateCdpConnectionAsync(handler, logger, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("WebSocket debug endpoint"))
{ logger.LogWarning(ex, "No CDP debug endpoint; re-probing /json/version and retrying"); /* re-discover then retry */ }

Prevention

When it happens

Trigger: Calling CreateCdpConnectionAsync (directly or via browser-logs session start) on a BrowserHost whose /json/version discovery failed or returned no webSocketDebuggerUrl, e.g. browser started without remote debugging enabled, discovery raced browser startup, or the browser died between discovery and connection.

Common situations: Custom/enterprise browser builds with DevTools debugging disabled; launching a browser binary that ignores the remote-debugging-port flag; startup race where the debugger endpoint is queried before Chromium exposes it; browser process exited immediately after launch.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Browsers/BrowserHost.cs:42

    public BrowserHostIdentity Identity { get; } = identity;

    public BrowserHostOwnership Ownership { get; } = ownership;

    public Uri? DebugEndpoint { get; } = debugEndpoint;

    public abstract int? ProcessId { get; }

    public string BrowserDisplayName { get; } = browserDisplayName;

    public abstract Task Termination { get; }

    public virtual async Task<IBrowserLogsCdpConnection> CreateCdpConnectionAsync(
        Func<BrowserLogsCdpProtocolEvent, ValueTask> eventHandler,
        ILogger<BrowserLogsSessionManager> logger,
        CancellationToken cancellationToken)
    {
        var debugEndpoint = DebugEndpoint ?? throw new InvalidOperationException("Tracked browser host does not expose a WebSocket debug endpoint.");
        return await BrowserLogsCdpConnection.ConnectAsync(debugEndpoint, eventHandler, logger, cancellationToken).ConfigureAwait(false);
    }

    public Task<IBrowserPageSession> CreatePageSessionAsync(
        string sessionId,
        Uri url,
        BrowserConnectionDiagnosticsLogger connectionDiagnostics,
        Func<BrowserLogsCdpProtocolEvent, ValueTask> eventHandler,
        CancellationToken cancellationToken)
    {
        return CreatePageSessionCoreAsync(sessionId, url, connectionDiagnostics, eventHandler, cancellationToken);
    }

    public abstract ValueTask DisposeAsync();

    private async Task<IBrowserPageSession> CreatePageSessionCoreAsync(
        string sessionId,
        Uri url,

View on GitHub (pinned to 25830f84bd)