MoonshotAI / MoonshotAI/kimi-code

Remote Control on iOS Safari: session page enters a crash–reload loop seconds after connecting (iPhone 12, iOS 18.5)

Open
#3,343 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

Summary

After starting kimi web --remote-control on Windows and logging in on an iPhone 12 (iOS 18.5) via the QR code, the session page renders for a few seconds and then Safari shows "A problem repeatedly occurred" (the page entered a crash–reload loop). A manual refresh sometimes brings the page back for a few seconds before it dies again. The same URL in a desktop browser is completely stable.

Reporter's original description (Chinese):

windows启动kimi rc之后,iphone扫码登录之后跳转到这里了。一会儿能刷新出来,但刷新出来之后一小会儿又跳到这个界面。

Evidence

  1. CLI stderr shows a strict 1:1 alternation of Remote device connected / Remote device disconnected. Each pair is one WS stream (open_stream → close). The web app normally holds 2+ concurrent WS connections (event channel + transcript channel), so only ever seeing one stream alive means the page dies before it can open the second — i.e. the renderer crashes within seconds of the first data arriving after each (re)load.
  2. Same URL on desktop is fine → the daemon, the relay, and the bandwidth path are exonerated. The only difference is the iOS WebContent process resource ceiling (iPhone 12 = 4 GB RAM).
  3. The user once glimpsed Safari's generic crash banner ("a problem occurred, reloaded") at the top — confirming renderer crashes (not a content error, not a redirect loop).
  4. Reproduces with multiple different sessions, not just one large one.
  5. Client-side code (kimi-code-app, current main) contains no automatic reload/navigation logic that could produce this page: the token dialog only reloads after manual token entry, the device switcher only navigates on manual selection, URL sync is replaceState-only, WS drops only trigger reconnects. A daemon outage would show the in-app "connecting" splash, not the Safari error page.

Mechanism (confirmed)

A self-sustaining crash loop:

page loads → WS connects → daemon starts pushing session data → iOS kills the WebContent process (memory/energy) → WS drops (device disconnected) → Safari auto-reloads → WS reconnects (device connected) → crash again → after a few cycles Safari gives up with "A problem repeatedly occurred".

Candidate resource amplifiers (from code reading — the exact kill point still needs on-device profiling)

  1. Every (re)connect re-seeds the transcript channel: sendTranscriptReset (kap-server transport/ws/v1/sessionEventBroadcaster.ts, TRANSCRIPT_RESET_TAIL_TURNS = 0) sends an empty snapshot with has_more_older: true, so the client immediately re-fetches transcript pages over REST and re-projects the session from scratch. Under rc this full re-fetch + re-projection happens on every flap.
  2. Grouped session-list drain: the client drains all GET /api/v2/sessions?view=by_workspace pages in the background on boot; the daemon recomputes grouping on every page with per-workspace serial alias resolution and no caching (kap-server routes/v2/sessions.ts — known N+1, ~3 s/page locally on machines with many workspaces). Over the relay + a home uplink this is minutes of continuous network/parse churn during exactly the first minute on the phone.
  3. Assets through the uplink: HTML/JS are served Cache-Control: no-cache after relay rewriting (remote-control.ts rewriteRemoteControlResponse), so every fresh load re-downloads the multi-MB bundle through the Windows machine's uplink.
  4. daemon WS server uses ws defaults (perMessageDeflate: false); the browser↔relay leg is relay-side and not visible from this repo — worth checking its close codes/timing.

What would help

  • Relay-side visibility into browser-stream close codes and timing for the affected device (the flapping is visible from the CLI side as connect/disconnect pairs).
  • Safari Web Inspector profiling from a Mac to identify the precise kill point (memory vs. a WebKit crash).
  • Consider a lighter mobile/rc boot path: bounded initial transcript window, pausing the grouped drain on metered/mobile connections, and caching rewritten assets.

Environment

  • daemon: kimi web --remote-control (experimental) on Windows 11
  • relay: code-rc.kimi.com
  • client: iPhone 12, iOS 18.5, Safari (on 5G)
  • control: same URL in desktop browser — stable

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 Safari Web Inspector profiling to distinguish a memory limit from a WebKit crash, and compare browser-stream close codes and timing on the relay. Trace reconnect behavior through transport/ws/v1/sessionEventBroadcaster.ts, routes/v2/sessions.ts, and remote-control.ts. Done means identifying the precise kill point and agreeing on a bounded mobile/remote-control mitigation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
mobile-dev, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.