Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions Issue_29213.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Unexpected model resolution: gemini-2.5-flash is mapped to gemini-3.5-flash

### What happened?

## `--model gemini-2.5-flash` is resolved to `gemini-3.5-flash` when using Vertex AI

## Summary

When invoking Gemini CLI with `--model gemini-2.5-flash`, the CLI appears to
resolve the request to `gemini-3.5-flash` instead of the specified model.

As a result, the request fails because my Vertex AI project does not have access
to `gemini-3.5-flash`.

## Environment

- Gemini CLI version: **0.58.0**
- Also reproduced on: **0.54.0**
- Node.js: **v24.13.0**
- Authentication: **Vertex AI (ADC)**

## Reproduction

Run:

```bash
echo "hello" | gemini \
--model gemini-2.5-flash \
--prompt ""
```

## Actual Behavior

The request fails with the following error:

```text
Error when talking to Gemini API

ModelNotFoundError: Publisher model
`projects/.../locations/us-central1/publishers/google/models/gemini-3.5-flash`
was not found or your project does not have access to it.
```

Although `gemini-2.5-flash` was specified, the CLI appears to send the request
to `gemini-3.5-flash`.

## Expected Behavior

The CLI should send the request to `gemini-2.5-flash` when it is explicitly
specified with:

```bash
--model gemini-2.5-flash
```

It should not resolve or rewrite the model name to `gemini-3.5-flash`.

## Additional Information

Using the same environment and authentication, the following command works as
expected:

```bash
echo "hello" | gemini \
--model gemini-2.5-pro \
--prompt ""
```

### What did you expect to happen?

It should not resolve or rewrite the model name to `gemini-3.5-flash`.

### Client information

<details>
<summary>Client Information</summary>

Run on Linux

Run `gemini` to enter the interactive CLI, then run the `/about` command.

```console
> /about
│ About Gemini CLI │
│ │
│ CLI Version 0.54.0 │
│ Git Commit a74b483d1 │
│ Model gemini-2.5-pro │
│ Sandbox no sandbox │
│ OS linux │
│ Auth Method vertex-ai │
│ GCP Project *** │
│ IDE Client VS Code │
```

</details>

### Login information

_No response_

### Anything else we need to know?

_No response_
6 changes: 0 additions & 6 deletions packages/core/src/config/defaultModelConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,12 +492,6 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
},
],
},
'gemini-2.5-flash': {
default: 'gemini-2.5-flash',
contexts: [
{ condition: { useGemini3_5Flash: true }, target: 'gemini-3.5-flash' },
],
},
'gemini-3-pro-preview': {
default: 'gemini-3-pro-preview',
contexts: [
Expand Down
30 changes: 26 additions & 4 deletions packages/core/src/config/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, it, expect } from 'vitest';
import { describe, it, expect, afterEach } from 'vitest';
import {
resolveModel,
resolveClassifierModel,
Expand All @@ -19,6 +19,7 @@ import {
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_3_5_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
setFlashModels,
supportsMultimodalFunctionResponse,
GEMINI_MODEL_ALIAS_PRO,
GEMINI_MODEL_ALIAS_FLASH,
Expand Down Expand Up @@ -787,7 +788,25 @@ describe('resolveModel Gemini 3.5 Flash GA', () => {
).toBe(PREVIEW_GEMINI_FLASH_MODEL);
});

it('should resolve all but preview flash models to gemini-3.5-flash when useGemini3_5Flash is true (dynamic)', () => {
describe('explicit --model gemini-2.5-flash (issue #29213)', () => {
afterEach(() => {
// Restore the module-level defaults mutated by setFlashModels().
setFlashModels('gemini-3-flash-preview', 'gemini-2.5-flash');
});

it('should not rewrite an explicitly requested gemini-2.5-flash to gemini-3.5-flash once GA rollout has flipped the default flash pointer (legacy)', () => {
// Simulates hasGemini35FlashGAAccess() mutating the default/preview
// flash pointers once GA is available for the user's backend (e.g.
// Vertex AI), as happens before routing an explicit --model flag.
setFlashModels('gemini-3.5-flash', 'gemini-3.5-flash');

expect(
resolveModel('gemini-2.5-flash', false, false, true, undefined, true),
).toBe('gemini-2.5-flash');
});
});

it('should resolve the flash alias to gemini-3.5-flash when useGemini3_5Flash is true, but leave explicitly requested concrete flash models untouched (dynamic)', () => {
const mockDynamicConfig = {
getExperimentalDynamicModelConfiguration: () => true,
modelConfigService,
Expand All @@ -803,16 +822,19 @@ describe('resolveModel Gemini 3.5 Flash GA', () => {
true,
),
).toBe('gemini-3.5-flash');
// An explicitly requested, pinned model ID must not be silently
// rewritten to a different model, even when the 3.5 flash GA alias
// upgrade is active. See https://github.com/google-gemini/gemini-cli/issues/29213
expect(
resolveModel(
DEFAULT_GEMINI_FLASH_MODEL,
'gemini-2.5-flash',
false,
false,
true,
mockDynamicConfig,
true,
),
).toBe('gemini-3.5-flash');
).toBe('gemini-2.5-flash');
expect(
resolveModel(
PREVIEW_GEMINI_FLASH_MODEL,
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/config/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,14 @@ export function resolveModel(
}

function isFlashModel(model: string): boolean {
// No `endsWith('flash')` catch-all: that would also match explicitly
// pinned model IDs like 'gemini-2.5-flash' and silently upgrade them.
return (
model === DEFAULT_GEMINI_FLASH_MODEL ||
model === PREVIEW_GEMINI_FLASH_MODEL ||
model === DEFAULT_GEMINI_3_5_FLASH_MODEL ||
model === SECONDARY_GEMINI_3_5_FLASH_MODEL ||
model === 'flash' ||
model.endsWith('flash')
model === 'flash'
);
}

Expand Down