louislam/uptime-kuma · error · Error

${WS_ERR_CODE[code] || `Unexpected status code: ${code}`}

Error message

${WS_ERR_CODE[code] || `Unexpected status code: ${code}`}

What it means

In WebSocketMonitorType.check (websocket-upgrade.js:31-51). attemptUpgrade returned a close code, but it is neither in the user's accepted_statuscodes_json list nor in the built-in WS_ERR_CODE map (codes 1002-1015, 3000/3003/3008). The thrown message is the friendly name when known, else 'Unexpected status code: <code>'.

Source

Thrown at server/monitor-types/websocket-upgrade.js:43

class WebSocketMonitorType extends MonitorType {
    name = "websocket-upgrade";

    /**
     * @inheritdoc
     */
    async check(monitor, heartbeat, _server) {
        const [message, code] = await this.attemptUpgrade(monitor);

        if (typeof code !== "undefined") {
            // If returned status code matches user controlled accepted status code(default 1000), return success
            if (checkStatusCode(code, JSON.parse(monitor.accepted_statuscodes_json))) {
                heartbeat.status = UP;
                heartbeat.msg = message;
                return; // success at this point
            }

            // Throw an error using friendly name if defined, fallback to generic msg
            throw new Error(WS_ERR_CODE[code] || `Unexpected status code: ${code}`);
        }
        // If no close code, then an error has occurred, display to user
        if (typeof message !== "undefined") {
            throw new Error(`${message}`);
        }
        // Throw generic error if nothing is defined, should never happen
        throw new Error("Unknown Websocket Error");
    }

    /**
     * Builds the WebSocket options object for authentication and TLS.
     * Supports basic auth, OAuth2 client credentials, and mTLS.
     * @param {object} monitor The monitor object for input parameters.
     * @returns {Promise<object>} The options object to pass to the WebSocket constructor.
     */
    async buildWsOptions(monitor) {
        const options = {};

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Add the observed code to the monitor's Accepted Status Codes list (accepted_statuscodes_json).
  2. If the code is 1006, investigate network/proxy interruption rather than adjusting accepted codes.
  3. Verify the WebSocket URL, subprotocol, and auth headers are correct so the server does not close with 1011/3xxx.
  4. Confirm reverse-proxy WebSocket upgrade support (e.g. nginx `proxy_set_header Upgrade $http_upgrade`).

Example fix

// before: accepted_statuscodes_json = [1000]
// server legitimately closes with 1001 (Going Away) during deploys
// after: accepted_statuscodes_json = [1000, 1001]
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the close code the server is likely to send is whitelisted
const WS_ERR_CODE = { 1000:'Normal', 1001:'Going Away', 1002:'Protocol error', 1011:'Internal Error', 1015:'TLS Handshake' /* ... */ };
function ensureCodeAccepted(code, acceptedJson) {
    const accepted = new Set(JSON.parse(acceptedJson || '[]'));
    if (!accepted.has(code)) {
        throw new Error(`WS close code ${code} (${WS_ERR_CODE[code]||'unknown'}) is not in accepted_statuscodes`);
    }
}

Type guard

function isWsCloseCode(v) { return typeof v === 'number' && v >= 1000 && v <= 4999; }

Try / catch

try {
    await monitor.check(monitor, heartbeat, server);
} catch (e) {
    // 1006 = abnormal closure — treat as network, not app-level, failure
    heartbeat.status = /Abnormal Closure|1006/.test(e.message) ? PENDING : DOWN;
    heartbeat.msg = e.message;
}

Prevention

When it happens

Trigger: Server closes with 1006 (abnormal closure / TCP drop), 1011 (internal server error), an application-level 4xxx code not whitelisted, or a 1000/1001 normal close that the user forgot to add to accepted_statuscodes_json.

Common situations: Default accepted codes do not match what the gateway returns; upstream reverse proxy (nginx/cloudflare) closes idle WebSockets with 1006; auth failure surfaces as a 3xxx code that is not whitelisted.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/4ba64da53130be2d. Report an issue: GitHub.