{"record":{"id":"15d1268e627978ed","repo":"louislam/uptime-kuma","slug":"unknown-websocket-error","errorCode":null,"errorMessage":"Unknown Websocket Error","messagePattern":"Unknown Websocket Error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"server/monitor-types/websocket-upgrade.js","lineNumber":50,"sourceCode":"        const [message, code] = await this.attemptUpgrade(monitor);\n\n        if (typeof code !== \"undefined\") {\n            // If returned status code matches user controlled accepted status code(default 1000), return success\n            if (checkStatusCode(code, JSON.parse(monitor.accepted_statuscodes_json))) {\n                heartbeat.status = UP;\n                heartbeat.msg = message;\n                return; // success at this point\n            }\n\n            // Throw an error using friendly name if defined, fallback to generic msg\n            throw new Error(WS_ERR_CODE[code] || `Unexpected status code: ${code}`);\n        }\n        // If no close code, then an error has occurred, display to user\n        if (typeof message !== \"undefined\") {\n            throw new Error(`${message}`);\n        }\n        // Throw generic error if nothing is defined, should never happen\n        throw new Error(\"Unknown Websocket Error\");\n    }\n\n    /**\n     * Builds the WebSocket options object for authentication and TLS.\n     * Supports basic auth, OAuth2 client credentials, and mTLS.\n     * @param {object} monitor The monitor object for input parameters.\n     * @returns {Promise<object>} The options object to pass to the WebSocket constructor.\n     */\n    async buildWsOptions(monitor) {\n        const options = {};\n\n        const timeoutMs = (monitor.timeout ?? 20) * 1000;\n        options.handshakeTimeout = timeoutMs;\n\n        // Parse custom headers if provided\n        if (monitor.headers) {\n            try {\n                options.headers = JSON.parse(monitor.headers);","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/monitor-types/websocket-upgrade.js#L32-L68","documentation":"Defensive fallback at websocket-upgrade.js:50. Fires only if attemptUpgrade returns neither a close code NOR a message — a state the code comment marks 'should never happen'. It guards against a future regression where attemptUpgrade resolves with [undefined, undefined].","triggerScenarios":"Programmatic: attemptUpgrade was modified to swallow the error event and resolve empty; a ws library version change altered event semantics so neither 'close' nor 'error' produced values; a mocked/stubbed monitor returned nothing.","commonSituations":"Custom fork of the monitor type that broke the promise resolution; ws library major-version upgrade that changed when 'error' vs 'close' fire.","solutions":["This indicates a code/library bug, not a config issue — inspect attemptUpgrade's promise resolution paths.","Upgrade or pin the `ws` dependency to a version tested against this monitor.","Add logging in attemptUpgrade's error/close handlers to capture which event fired with what payload."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Defensive: assert attemptUpgrade never returns [undefined, undefined] before throwing the generic error\nconst [msg, code] = await this.attemptUpgrade(monitor);\nif (msg == null && code == null) {\n    log.error('attemptUpgrade returned empty result — ws handler regression suspected');\n}","typeGuard":"function hasWsSignal([msg, code]) { return msg != null || code != null; }","tryCatchPattern":"try {\n    await monitor.check(monitor, heartbeat, server);\n} catch (e) {\n    if (e.message === 'Unknown Websocket Error') {\n        log.error('ws monitor produced no signal — report upstream; ws lib version:', require('ws/package.json').version);\n    }\n}","preventionTips":["Pin the ws library version and re-test on upgrades.","Add a regression test asserting attemptUpgrade always yields at least one signal."],"tags":["websocket","defensive","monitor","bug"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}