cloudflare / cloudflare/workers-sdk
[vite-plugin] Non-101 WebSocket upgrade responses are destroyed instead of delivered to the client in dev
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
### What versions & operating system are you using?
System:
OS: macOS 26.5.2
CPU: (10) arm64 Apple M4
Memory: 114.05 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.12.0
npm: 11.6.2
bun: 1.3.14
npmPackages:
@cloudflare/vite-plugin: ^1.52.0 => 1.52.0
wrangler: ^4.122.0 => 4.122.0
### Please provide a link to a minimal reproduction
https://github.com/colinchadwick/vite-plugin-ws-rejection-repro
### Describe the Bug
In dev mode, when a Worker responds to a WebSocket upgrade request with a **non-101 HTTP response** (e.g. `401` to reject an unauthenticated upgrade), the client socket is **destroyed without any HTTP response** — the client never receives the status code. This breaks native WebSocket clients that rely on the status to distinguish "rejected — refresh and retry" from a network failure.
Rejecting a WebSocket upgrade with a normal HTTP status is the standard RFC 6455 mechanism. RFC 6455 §4.1:
> If the status code received from the server is not 101, the client handles the response per HTTP [RFC2616] procedures. In particular, the client might perform authentication if it receives a 401 status code...
**Steps to reproduce:**
1. `npm install`
2. `npm run dev`
3. `npm run client` (sends a WS upgrade request to a Worker that responds `401` without upgrading)
**Expected** — the Worker's `401` response is delivered on the upgrade request:
```markdown
RECEIVED RESPONSE:
HTTP 401 Unauthorized
Content-Type: text/plain;charset=UTF-8
...
rejected: unauthorized
```
**Actual** — the connection is destroyed with no bytes delivered.
**Root cause** — `packages/vite-plugin-cloudflare/src/websockets.ts` (`handleWebSocket`):
```js
const workerWebSocket = response.webSocket;
if (!workerWebSocket) {
socket.destroy();
return;
}
```
There is no code path that writes a non-101 response back to the client; the relay only supports 101-with-webSocket or destroy.
### Please provide any relevant error logs
```markdown
CONNECTION DESTROYED, NO HTTP RESPONSE: socket hang up
Contributor guide
Research direction
Start in packages/vite-plugin-cloudflare/src/websockets.ts at handleWebSocket and reproduce the issue with the linked minimal reproduction using npm install, npm run dev, and npm run client. Trace the non-101 upgrade path and verify that the Worker's 401 response, including its status and body, reaches the client instead of destroying the socket.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend, networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100