MoonshotAI / MoonshotAI/kimi-code

WebSocket connection fails in local dev mode when browser uses localhost and server binds 127.0.0.1

Open
#1,157 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

What version of Kimi Code is running?

0.20.1 (commit 54baf5d)

Which open platform/subscription were you using?

Local development / none

Which model were you using?

N/A

What platform is your computer?

Darwin 24.6.0 arm64 arm

What issue are you seeing?

When running pnpm dev:web and pnpm dev:server to debug Kimi Code Web locally, the web UI loads fine after entering the server token, but the WebSocket connection to /api/v1/ws keeps failing with a "WebSocket error" toast in the status bar.

The browser console shows the WebSocket closes with code 1006 (abnormal closure). Inspecting the handshake shows the server responds with 403 Forbidden during the WebSocket upgrade.

What steps can reproduce the bug?
  1. Clone the repo and run pnpm install.
  2. In one terminal, run pnpm dev:server to start the local server.
  3. In another terminal, run pnpm dev:web to start the Vite dev server.
  4. Open Chrome at http://localhost:5175.
  5. Enter the server token when prompted.
  6. Open or create a session.
  7. Observe the status bar shows "实时连接出错 / WebSocket error" and the WebSocket repeatedly reconnects.
What is the expected behavior?

The WebSocket should connect successfully in local dev mode when the browser opens http://localhost:5175 and the server binds 127.0.0.1:58627, so that streaming events work without manual workarounds.

Additional information

The root cause appears to be the Origin check added in PR #1006 (feat(server): add bearer-token auth and safe host exposure).

During the WebSocket upgrade, the browser sends:

Origin: http://localhost:5175

Vite's dev proxy forwards the request to the server with:

Host: 127.0.0.1:58627

The server's isOriginAllowed() compares localhost and 127.0.0.1, treats them as different origins, and rejects the handshake with 403.

This only affects the WebSocket path because changeOrigin: true rewrites the Host header but does not rewrite the Origin header for WebSocket upgrades.

Upstream Vite issue for the same class of problem: https://github.com/vitejs/vite/issues/16557

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the local pnpm dev:web and pnpm dev:server entry points, reproduce the failed /api/v1/ws handshake, and trace the server's isOriginAllowed() check described in PR #1006. Compare the browser Origin with the proxied Host, then verify that the WebSocket connects successfully from http://localhost:5175 and streaming events work without a workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, vite
Domain
backend, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.