MoonshotAI / MoonshotAI/kimi-code

Concurrent first launches return inconsistent device IDs

Open
#3,185 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.38.0 / main at 9a715820c41f

Which open platform/subscription were you using?

Not applicable; this happens while the local device identity is initialized, before authentication.

Which model were you using?

Not applicable.

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64. The read-then-write race is platform-independent.

What issue are you seeing?

createKimiDeviceId() does an uncoordinated read-then-write when device_id does not exist. If multiple Kimi Code processes start against a fresh home directory at the same time, every process can generate and return a different UUID, while only one of those values remains in device_id after the writes finish.

In a synchronized 96-process reproduction, all 96 calls returned distinct IDs and 95 differed from the final persisted ID:

{
  "workers": 96,
  "returnedIds": 96,
  "mismatches": 95
}

Those transient IDs are immediately used in X-Msh-Device-Id and telemetry. Every racing process also invokes onFirstLaunch, so one installation may emit multiple first-launch events carrying different device IDs.

What steps can reproduce the bug?
  1. Clone the repository and use Node.js 24.
  2. Start many child processes and hold them on a barrier after importing packages/oauth/src/identity.ts.
  3. Release the barrier so every child calls createKimiDeviceId() with the same previously nonexistent home directory.
  4. Compare every returned value with the final contents of <homeDir>/device_id.

The essential worker operation is:

const { createKimiDeviceId } = await import('./packages/oauth/src/identity.ts');
const id = createKimiDeviceId(sharedFreshHomeDir);
process.stdout.write(id);

Synchronizing the workers immediately before the call makes the mismatch deterministic on the tested machine.

What is the expected behavior?

Initialization should be atomic across processes. All concurrent callers for the same fresh home directory should return the single ID that is persisted, and onFirstLaunch should run only for the process that successfully creates that ID.

Additional information

The race is at packages/oauth/src/identity.ts: the initial readKimiDeviceId() check and the later writeFileSync() are separate operations, and the write replaces an existing file instead of using create-if-absent semantics.

Contribution
  • I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)

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 packages/oauth/src/identity.ts, especially the separate readKimiDeviceId() and writeFileSync() operations in createKimiDeviceId(). Run the synchronized multi-process reproduction against a fresh home directory; done means concurrent callers return the one persisted device ID and onFirstLaunch runs only for the creator.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.