google-gemini / google-gemini/gemini-cli

bug: interrupted Whisper downloads are treated as installed models

Open
#28,644 2 comments 0 reactions 0 assignees View on GitHub
area/core effort/medium status/bot-triaged
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.