MoonshotAI / MoonshotAI/kimi-code
[Bug] File diff buffers complete Git stdout before applying the 1 MiB limit
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?
Current main at f06eb5c60e0a4e51162d1854dda1db41892b457c.
Which open platform/subscription were you using?
Not applicable. This occurs in the local Git filesystem service before any model request.
Which model were you using?
Not applicable.
What platform is your computer?
Linux x86_64.
What issue are you seeing?
The file-diff services return at most 1 MiB, but currently accumulate the complete git diff stdout before applying that limit. A large generated or modified text file can therefore create a transient memory spike proportional to the complete diff even though the caller receives only 1 MiB.
The limit is also applied using JavaScript string length rather than UTF-8 bytes. A multibyte diff can exceed the intended byte ceiling while reporting truncated: false.
git diff stdout: N bytes
|
v
complete JavaScript string: N bytes
|
v
slice after process exit
|
v
response: at most 1 MiB
A representative 24 MiB modified file increased peak RSS to 331 MiB on the current implementation. Bounding capture reduced the same run to 231 MiB. This measurement includes Git, fixture data, stream decoding, and V8 overhead; the relevant contract is that the retained response buffer should not scale with complete stdout.
This is a transient memory amplification/OOM risk, not evidence of a persistent memory leak.
What steps can reproduce the bug?
- Create a Git repository and commit a small text file.
- Replace it with a large textual payload.
- Request its diff through
FsGitService.diff()or the v2IGitService.diff(). - Observe peak RSS while the service collects the complete subprocess output.
The byte-limit error has a smaller deterministic reproduction:
writeFileSync(file, '界'.repeat(400_000));
const result = await service.diff(repo, 'large.txt', file);
expect(result.truncated).toBe(true);
expect(Buffer.byteLength(result.diff, 'utf8')).toBeLessThanOrEqual(1_048_576);
On current main, both implementations return truncated: false: 400,000 UTF-16 code units are below the character-count limit even though the encoded diff is approximately 1.2 MiB.
What is the expected behavior?
The services should retain no more than 1 MiB of valid UTF-8 while consuming stdout, continue draining discarded subprocess output, and report truncated: true when additional bytes are observed.
Additional information
Both implementations are affected:
packages/agent-core/src/services/fs/fsGitService.tspackages/agent-core-v2/src/app/git/gitService.ts
PR #1285 is relevant precedent: it bounded foreground shell-command output after unbounded subprocess capture was shown to terminate the process.
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 FsGitService.diff() in packages/agent-core/src/services/fs/fsGitService.ts and IGitService.diff() in packages/agent-core-v2/src/app/git/gitService.ts; compare their subprocess stdout handling with the bounded-output precedent in PR #1285. Run the provided multibyte reproduction and large-diff scenario. Done means both services retain at most 1 MiB of valid UTF-8 while draining stdout and report truncation when additional bytes are observed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, typescript
- Domain
- backend, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100