Skip to content

[fix] Handle unknown status codes in abortHandshake() - #2351

Closed
fizzbeom wants to merge 1 commit into
websockets:masterfrom
fizzbeom:fix/abort-handshake-unknown-status
Closed

fizzbeom wants to merge 1 commit into
websockets:masterfrom
fizzbeom:fix/abort-handshake-unknown-status

Conversation

@fizzbeom

@fizzbeom fizzbeom commented Nov 4, 2026

Copy link
Copy Markdown

If the verifyClient callback rejects a client with a status code that is not in http.STATUS_CODES (for example cb(false, 499)), abortHandshake() throws:

TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received undefined
    at Buffer.byteLength (node:buffer)
    at abortHandshake (lib/websocket-server.js)

The error is thrown from inside the user's callback, and no response is written, so the socket stays open until the client gives up. If a message is passed (cb(false, 499, 'Token expired')), the response is sent but the status line is HTTP/1.1 499 undefined.

This change falls back to Unknown as the reason phrase when the code is not in http.STATUS_CODES, similar to what http.ServerResponse does (HTTP/1.1 499 unknown). It also uses that phrase as the default body.

For context, in ws 1.x the status line was built from the name argument ('HTTP/1.1 ' + code + ' ' + name), so custom codes worked. Since 3.x the reason phrase always comes from http.STATUS_CODES[code]. doc/ws.md still describes name as "the HTTP reason phrase", although it is now used as the body. I left the docs and that behaviour alone here, but I can update the docs in this PR if you prefer.

A test is added next to the existing "can reject client asynchronously w/ status code" test. Without the fix it fails with the TypeError above.

This PR was generated with AI (Claude Code).

If the `verifyClient` callback rejects a client with a status code that
is not in `http.STATUS_CODES`, `abortHandshake()` throws a `TypeError`
and leaves the socket open, or writes `undefined` as the reason phrase
if a message is provided. Fall back to `Unknown` instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lpinca

lpinca commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

What is the use case? I mean, what is the status code not in http.STATUS_CODES that the user want to use? I can't remember open issues for this.

@lpinca

lpinca commented Nov 5, 2026

Copy link
Copy Markdown
Member

The error is thrown from inside the user's callback, and no response is written, so the socket stays open until the client gives up.

That error should cause the process to exit and, consequently, the socket to close.

@fizzbeom

fizzbeom commented Nov 5, 2026

Copy link
Copy Markdown
Author

You're right, thanks for checking. The TypeError is uncaught and terminates the process; the "socket stays open" part of my description was wrong, sorry about that.

As for the use case, I don't have a concrete user report. I found it while reading abortHandshake(). Since there is no open issue asking for it, I'll close this.

@fizzbeom fizzbeom closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants