google-gemini / google-gemini/gemini-cli
bug: interrupted Whisper downloads are treated as installed models
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## What happened?
`WhisperModelManager.downloadModel()` writes a large model directly to its final installed filename but does not wait for the write stream to finish, handle write errors/backpressure, or remove incomplete output.
In `packages/core/src/voice/whisperModelManager.ts:52-100`:
- `fs.createWriteStream(destination)` targets the final model path.
- `writer.write(value)` ignores a `false` return value, so backpressure is not respected.
- The `finally` block calls `writer.end()` but the method does not await `finish` or reject on the writer's `error` event.
- An interrupted response or disk failure leaves the destination file behind.
The installation check only tests whether the model path exists, so that partial file is subsequently treated as an installed model.
## How can this be reproduced?
1. Start downloading a Whisper model.
2. Interrupt the process, disconnect the network, or make the destination run out of space after some bytes have been written.
3. Restart Gemini CLI and open voice mode.
4. The partial final-path file is detected as installed and passed to `whisper-stream`, which then fails or behaves unpredictably.
A unit test can reproduce this without a real download by mocking a response body and making the write stream emit `error`, or by ending the response before the declared content length.
## What did you expect to happen?
The model should become visible as installed only after the complete response has been durably written and validated. Failed downloads should reject and remove their temporary output.
## Why this matters
Whisper models are large, making interruption and backpressure realistic. The current behavior can leave voice mode permanently broken until the user manually finds and deletes the corrupt file.
## Suggested direction
- Write to a sibling temporary file.
- Use a backpressure-aware pipeline and await completion.
- Validate the expected size and preferably a published checksum.
- Atomically rename the temporary file to the final model path.
- Remove temporary output on every failure path.
`packages/cli/src/commands/gemma/setup.ts` already contains a useful in-repository pattern: temporary `.downloading` output, backpressure handling, awaiting `finish`/`error`, and atomic rename.
## Client information
Found by source audit on current `main`, commit `f47d6c6f7`. The model manager currently has no dedicated unit test file.
Contributor guide
Research direction
Start in packages/core/src/voice/whisperModelManager.ts:52-100, then compare the download handling in packages/cli/src/commands/gemma/setup.ts. Add focused unit coverage using a mocked response and failing write stream, since the manager currently has no dedicated tests. Done means interrupted or failed downloads reject, remove incomplete output, and never make a partial model appear installed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100