MoonshotAI / MoonshotAI/kimi-code
Concurrent first launches return inconsistent device IDs
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?
- Clone the repository and use Node.js 24.
- Start many child processes and hold them on a barrier after importing
packages/oauth/src/identity.ts. - Release the barrier so every child calls
createKimiDeviceId()with the same previously nonexistent home directory. - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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