{"record":{"id":"683a519aedfa4384","repo":"microsoft/aspire","slug":"aspire-terminal-ws-closed-abnormally","errorCode":null,"errorMessage":"[aspire-terminal] WS closed abnormally","messagePattern":"\\[aspire-terminal\\] WS closed abnormally","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js","lineNumber":1310,"sourceCode":"        // close-frame, 1011 = server error, etc.).\n        const closeInfo = {\n            generation: myGeneration,\n            currentGeneration: state.reconnect.generation,\n            stale: myGeneration !== state.reconnect.generation,\n            code: ev?.code,\n            reason: ev?.reason,\n            wasClean: ev?.wasClean,\n        };\n        dbg(state, 'client.onClose', closeInfo);\n        // Abnormal close (1006 = no close frame, !wasClean) is highly\n        // suggestive of a transport-level kill. Surface this at warn so\n        // it shows up in the default browser console without needing the\n        // aspire-terminal-debug flag. Normal close (1000) under stress\n        // means the proxy gracefully closed after upstream EOF — also\n        // worth a one-liner to correlate with server-side pump logs.\n        if (ev && (ev.code !== 1000 || !ev.wasClean)) {\n            try {\n                console.warn('[aspire-terminal] WS closed abnormally', closeInfo);\n            } catch { /* ignore */ }\n        }\n        if (myGeneration !== state.reconnect.generation) {\n            return;\n        }\n        if (!state.reconnect.enabled) {\n            return;\n        }\n        notifyToolbar(state); // back to \"connecting\"\n        scheduleReconnect(state);\n    };\n\n    state.client = client;\n    try {\n        client.connect();\n    } catch (e) {\n        dbg(state, 'connectClient: connect threw', { error: e?.message });\n        // Treat a synchronous connect failure (e.g. malformed URL) as a","sourceCodeStart":1292,"sourceCodeEnd":1328,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js#L1292-L1328","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Verify the AppHost and the target resource are still running — a crashed resource or AppHost legitimately closes the stream.","Reload the dashboard page if reconnect does not restore the stream; the component auto-reconnects unless reconnect is disabled.","If it reproduces under stress, look for proxy idle/timeouts between the browser and dashboard (reverse proxies, dev tunnels) and raise their WebSocket timeout."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The component already reconnects; application-level guard:\nws.onclose = (ev) => {\n  if (ev.code !== 1000 || !ev.wasClean) {\n    console.warn('WS closed abnormally', { code: ev.code, reason: ev.reason, wasClean: ev.wasClean });\n    scheduleReconnectWithBackoff();\n  }\n};","preventionTips":["Keep the dashboard and AppHost on versions where terminal-log reconnect is enabled.","Watch server-side terminal-log pump logs to correlate abnormal closes.","Raise WebSocket idle timeouts on any reverse proxy/dev tunnel between browser and dashboard.","Avoid suspending the browser tab mid-stream during long log sessions; reload on resume."],"tags":["websocket","dashboard","streaming","reconnect"],"backgroundTag":"websocket-disconnected","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}