microsoft/aspire · warning

[aspire-terminal] WS closed abnormally

Error message

[aspire-terminal] WS closed abnormally

What it means

The terminal log-streaming webview in Aspire Dashboard logs this console warning when a WebSocket used to stream terminal output closes with any code other than a clean 1000 close (or closes uncleanly). It is a diagnostic warning, not a thrown error: the component then proceeds through its reconnect logic. It usually indicates the terminal-log proxy dropped or reset the connection.

Solutions

  1. Check the dashboard/AppHost server logs around the disconnect time for terminal-log proxy pump errors; the warning is intentionally surfaced to correlate with server-side logs.
  2. Verify the AppHost and the target resource are still running — a crashed resource or AppHost legitimately closes the stream.
  3. Reload the dashboard page if reconnect does not restore the stream; the component auto-reconnects unless reconnect is disabled.
  4. If it reproduces under stress, look for proxy idle/timeouts between the browser and dashboard (reverse proxies, dev tunnels) and raise their WebSocket timeout.
Defensive patterns

Strategy: retry

Try / catch

// The component already reconnects; application-level guard:
ws.onclose = (ev) => {
  if (ev.code !== 1000 || !ev.wasClean) {
    console.warn('WS closed abnormally', { code: ev.code, reason: ev.reason, wasClean: ev.wasClean });
    scheduleReconnectWithBackoff();
  }
};

Prevention

When it happens

Trigger: The browser's WebSocket onclose event fires with ev.code !== 1000 or ev.wasClean === false, e.g. the dashboard backend terminal-log proxy died, the AppHost terminated, network interruption, or the server aborted the socket mid-stream.

Common situations: AppHost crash or restart while viewing a resource's terminal logs in the dashboard; proxy timeout under heavy log volume; browser tab suspended/resumed killing the socket; server-side pump exception closing the WebSocket abruptly.

Related errors


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

Appendix: source

Thrown at src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:1310

        // close-frame, 1011 = server error, etc.).
        const closeInfo = {
            generation: myGeneration,
            currentGeneration: state.reconnect.generation,
            stale: myGeneration !== state.reconnect.generation,
            code: ev?.code,
            reason: ev?.reason,
            wasClean: ev?.wasClean,
        };
        dbg(state, 'client.onClose', closeInfo);
        // Abnormal close (1006 = no close frame, !wasClean) is highly
        // suggestive of a transport-level kill. Surface this at warn so
        // it shows up in the default browser console without needing the
        // aspire-terminal-debug flag. Normal close (1000) under stress
        // means the proxy gracefully closed after upstream EOF — also
        // worth a one-liner to correlate with server-side pump logs.
        if (ev && (ev.code !== 1000 || !ev.wasClean)) {
            try {
                console.warn('[aspire-terminal] WS closed abnormally', closeInfo);
            } catch { /* ignore */ }
        }
        if (myGeneration !== state.reconnect.generation) {
            return;
        }
        if (!state.reconnect.enabled) {
            return;
        }
        notifyToolbar(state); // back to "connecting"
        scheduleReconnect(state);
    };

    state.client = client;
    try {
        client.connect();
    } catch (e) {
        dbg(state, 'connectClient: connect threw', { error: e?.message });
        // Treat a synchronous connect failure (e.g. malformed URL) as a

View on GitHub (pinned to 25830f84bd)