From 290f034f6b77c1cbbfa362da4839657b52d78d68 Mon Sep 17 00:00:00 2001 From: Nixxx19 Date: Wed, 4 Mar 2026 11:12:17 +0530 Subject: [PATCH 1/4] fix: improve error message when OAuth succeeds but project ID is required Fixes #15749 The issue was that OAuth authentication would succeed (showing 'Authentication succeeded'), but then setupUser would throw ProjectIdRequiredError, which was caught and displayed as 'Failed to login. Message: ...'. This was confusing because authentication had actually succeeded. Now ProjectIdRequiredError is caught specifically and the error message is shown directly without the 'Failed to login' prefix, making it clear that OAuth succeeded but account setup requires GOOGLE_CLOUD_PROJECT to be set. --- packages/cli/src/core/auth.ts | 9 +++++++++ packages/cli/src/ui/AppContainer.tsx | 7 +++++++ packages/cli/src/ui/auth/useAuth.ts | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/packages/cli/src/core/auth.ts b/packages/cli/src/core/auth.ts index f49fdecf767..f0b8015013d 100644 --- a/packages/cli/src/core/auth.ts +++ b/packages/cli/src/core/auth.ts @@ -10,6 +10,7 @@ import { getErrorMessage, ValidationRequiredError, isAccountSuspendedError, + ProjectIdRequiredError, } from '@google/gemini-cli-core'; import type { AccountSuspensionInfo } from '../ui/contexts/UIStateContext.js'; @@ -54,6 +55,14 @@ export async function performInitialAuth( }, }; } + if (e instanceof ProjectIdRequiredError) { + // OAuth succeeded but account setup requires project ID + // Show the error message directly without "Failed to login" prefix + return { + authError: getErrorMessage(e), + accountSuspensionInfo: null, + }; + } return { authError: `Failed to login. Message: ${getErrorMessage(e)}`, accountSuspensionInfo: null, diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index a865f505afd..b149aa0f747 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -80,6 +80,7 @@ import { type ConsentRequestPayload, type AgentsDiscoveredPayload, ChangeAuthRequestedError, + ProjectIdRequiredError, CoreToolCallStatus, generateSteeringAckMessage, buildUserSteeringHintPrompt, @@ -771,6 +772,12 @@ export const AppContainer = (props: AppContainerProps) => { if (e instanceof ChangeAuthRequestedError) { return; } + if (e instanceof ProjectIdRequiredError) { + // OAuth succeeded but account setup requires project ID + // Show the error message directly without "Failed to authenticate" prefix + onAuthError(e.message); + return; + } onAuthError( `Failed to authenticate: ${e instanceof Error ? e.message : String(e)}`, ); diff --git a/packages/cli/src/ui/auth/useAuth.ts b/packages/cli/src/ui/auth/useAuth.ts index 3faec2d5a83..afd438bb001 100644 --- a/packages/cli/src/ui/auth/useAuth.ts +++ b/packages/cli/src/ui/auth/useAuth.ts @@ -12,6 +12,7 @@ import { loadApiKey, debugLogger, isAccountSuspendedError, + ProjectIdRequiredError, } from '@google/gemini-cli-core'; import { getErrorMessage } from '@google/gemini-cli-core'; import { AuthState } from '../types.js'; @@ -143,6 +144,10 @@ export const useAuthCommand = ( appealUrl: suspendedError.appealUrl, appealLinkText: suspendedError.appealLinkText, }); + } else if (e instanceof ProjectIdRequiredError) { + // OAuth succeeded but account setup requires project ID + // Show the error message directly without "Failed to login" prefix + onAuthError(getErrorMessage(e)); } else { onAuthError(`Failed to login. Message: ${getErrorMessage(e)}`); } From 0dbd7d8426e1516093cc2bd0b4eedec18913612f Mon Sep 17 00:00:00 2001 From: Nixxx19 Date: Wed, 4 Mar 2026 12:28:54 +0530 Subject: [PATCH 2/4] test: add tests for ProjectIdRequiredError handling --- packages/cli/src/core/auth.test.ts | 19 +++++++++++++++++++ packages/cli/src/ui/auth/useAuth.test.tsx | 22 +++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/core/auth.test.ts b/packages/cli/src/core/auth.test.ts index f28e826f491..5db9cd54498 100644 --- a/packages/cli/src/core/auth.test.ts +++ b/packages/cli/src/core/auth.test.ts @@ -9,6 +9,7 @@ import { performInitialAuth } from './auth.js'; import { type Config, ValidationRequiredError, + ProjectIdRequiredError, AuthType, } from '@google/gemini-cli-core'; @@ -116,4 +117,22 @@ describe('auth', () => { AuthType.LOGIN_WITH_GOOGLE, ); }); + + it('should return ProjectIdRequiredError message without "Failed to login" prefix', async () => { + const projectIdError = new ProjectIdRequiredError(); + vi.mocked(mockConfig.refreshAuth).mockRejectedValue(projectIdError); + const result = await performInitialAuth( + mockConfig, + AuthType.LOGIN_WITH_GOOGLE, + ); + expect(result).toEqual({ + authError: + 'This account requires setting the GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID env var. See https://goo.gle/gemini-cli-auth-docs#workspace-gca', + accountSuspensionInfo: null, + }); + expect(result.authError).not.toContain('Failed to login'); + expect(mockConfig.refreshAuth).toHaveBeenCalledWith( + AuthType.LOGIN_WITH_GOOGLE, + ); + }); }); diff --git a/packages/cli/src/ui/auth/useAuth.test.tsx b/packages/cli/src/ui/auth/useAuth.test.tsx index 36d9aeec4f6..20a02ffb213 100644 --- a/packages/cli/src/ui/auth/useAuth.test.tsx +++ b/packages/cli/src/ui/auth/useAuth.test.tsx @@ -15,7 +15,11 @@ import { } from 'vitest'; import { renderHook } from '../../test-utils/render.js'; import { useAuthCommand, validateAuthMethodWithSettings } from './useAuth.js'; -import { AuthType, type Config } from '@google/gemini-cli-core'; +import { + AuthType, + type Config, + ProjectIdRequiredError, +} from '@google/gemini-cli-core'; import { AuthState } from '../types.js'; import type { LoadedSettings } from '../../config/settings.js'; import { waitFor } from '../../test-utils/async.js'; @@ -288,5 +292,21 @@ describe('useAuth', () => { expect(result.current.authState).toBe(AuthState.Updating); }); }); + + it('should handle ProjectIdRequiredError without "Failed to login" prefix', async () => { + const projectIdError = new ProjectIdRequiredError(); + (mockConfig.refreshAuth as Mock).mockRejectedValue(projectIdError); + const { result } = renderHook(() => + useAuthCommand(createSettings(AuthType.LOGIN_WITH_GOOGLE), mockConfig), + ); + + await waitFor(() => { + expect(result.current.authError).toBe( + 'This account requires setting the GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID env var. See https://goo.gle/gemini-cli-auth-docs#workspace-gca', + ); + expect(result.current.authError).not.toContain('Failed to login'); + expect(result.current.authState).toBe(AuthState.Updating); + }); + }); }); }); From 570530b59d29bab8fe4b5aa1861a56113b1bf6a6 Mon Sep 17 00:00:00 2001 From: Nixxx19 Date: Wed, 4 Mar 2026 12:38:47 +0530 Subject: [PATCH 3/4] chore: add PR description template --- PR_DESCRIPTION.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 PR_DESCRIPTION.md diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md new file mode 100644 index 00000000000..c4f14c27007 --- /dev/null +++ b/PR_DESCRIPTION.md @@ -0,0 +1,81 @@ +## Summary + +Fixes confusing error message when OAuth authentication succeeds but account +setup requires `GOOGLE_CLOUD_PROJECT`. The error message now correctly reflects +that OAuth succeeded but account configuration requires a project ID, removing +the misleading "Failed to login" prefix. + +## Details + +When authenticating with a workspace Google account that requires +`GOOGLE_CLOUD_PROJECT`, the OAuth flow succeeds (showing "Authentication +succeeded"), but then `setupUser()` throws `ProjectIdRequiredError` if the +project ID is not set. Previously, this error was caught and displayed with a +"Failed to login. Message:" prefix, which was confusing since OAuth had already +succeeded. + +This PR: + +- Catches `ProjectIdRequiredError` specifically in all three authentication + error handling paths +- Displays the error message directly without the "Failed to login" or "Failed + to authenticate" prefix +- Makes it clear that OAuth succeeded but account setup requires additional + configuration + +**Error handling paths updated:** + +1. `performInitialAuth()` - Initial authentication during startup +2. `useAuthCommand()` - Authentication hook in UI +3. `handleAuthSelect()` - Auth selection handler in AppContainer + +## Related Issues + +Fixes #15749 + +## How to Validate + +1. **Test with workspace account requiring project ID:** + + ```bash + # Ensure GOOGLE_CLOUD_PROJECT is not set + unset GOOGLE_CLOUD_PROJECT + unset GOOGLE_CLOUD_PROJECT_ID + + # Start CLI + npm start + ``` + +2. **Select "Login with Google" and authenticate with a workspace account** + +3. **Expected behavior:** + - See "Authentication succeeded" message + - Then see error: + `This account requires setting the GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID env var. See https://goo.gle/gemini-cli-auth-docs#workspace-gca` + - **Should NOT** see "Failed to login. Message:" prefix + +4. **Verify tests pass:** + ```bash + npm test -- packages/cli/src/core/auth.test.ts packages/cli/src/ui/auth/useAuth.test.tsx + ``` + +## Pre-Merge Checklist + +- [x] Updated relevant documentation and README (if needed) +- [x] Added/updated tests (if needed) +- [ ] Noted breaking changes (if any) - None +- [ ] Validated on required platforms/methods: + - [ ] MacOS + - [x] npm run + - [ ] npx + - [ ] Docker + - [ ] Podman + - [ ] Seatbelt + - [ ] Windows + - [ ] npm run + - [ ] npx + - [ ] Docker + - [ ] Linux + - [ ] npm run + - [ ] npx + - [ ] Docker From f650d58be0320383d05908a3c727fc72b4aeadbe Mon Sep 17 00:00:00 2001 From: Nixxx19 Date: Wed, 4 Mar 2026 13:10:27 +0530 Subject: [PATCH 4/4] chore: clean up PR description and use getErrorMessage for project ID error --- PR_DESCRIPTION.md | 81 ---------------------------- packages/cli/src/ui/AppContainer.tsx | 2 +- 2 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 PR_DESCRIPTION.md diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md deleted file mode 100644 index c4f14c27007..00000000000 --- a/PR_DESCRIPTION.md +++ /dev/null @@ -1,81 +0,0 @@ -## Summary - -Fixes confusing error message when OAuth authentication succeeds but account -setup requires `GOOGLE_CLOUD_PROJECT`. The error message now correctly reflects -that OAuth succeeded but account configuration requires a project ID, removing -the misleading "Failed to login" prefix. - -## Details - -When authenticating with a workspace Google account that requires -`GOOGLE_CLOUD_PROJECT`, the OAuth flow succeeds (showing "Authentication -succeeded"), but then `setupUser()` throws `ProjectIdRequiredError` if the -project ID is not set. Previously, this error was caught and displayed with a -"Failed to login. Message:" prefix, which was confusing since OAuth had already -succeeded. - -This PR: - -- Catches `ProjectIdRequiredError` specifically in all three authentication - error handling paths -- Displays the error message directly without the "Failed to login" or "Failed - to authenticate" prefix -- Makes it clear that OAuth succeeded but account setup requires additional - configuration - -**Error handling paths updated:** - -1. `performInitialAuth()` - Initial authentication during startup -2. `useAuthCommand()` - Authentication hook in UI -3. `handleAuthSelect()` - Auth selection handler in AppContainer - -## Related Issues - -Fixes #15749 - -## How to Validate - -1. **Test with workspace account requiring project ID:** - - ```bash - # Ensure GOOGLE_CLOUD_PROJECT is not set - unset GOOGLE_CLOUD_PROJECT - unset GOOGLE_CLOUD_PROJECT_ID - - # Start CLI - npm start - ``` - -2. **Select "Login with Google" and authenticate with a workspace account** - -3. **Expected behavior:** - - See "Authentication succeeded" message - - Then see error: - `This account requires setting the GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_PROJECT_ID env var. See https://goo.gle/gemini-cli-auth-docs#workspace-gca` - - **Should NOT** see "Failed to login. Message:" prefix - -4. **Verify tests pass:** - ```bash - npm test -- packages/cli/src/core/auth.test.ts packages/cli/src/ui/auth/useAuth.test.tsx - ``` - -## Pre-Merge Checklist - -- [x] Updated relevant documentation and README (if needed) -- [x] Added/updated tests (if needed) -- [ ] Noted breaking changes (if any) - None -- [ ] Validated on required platforms/methods: - - [ ] MacOS - - [x] npm run - - [ ] npx - - [ ] Docker - - [ ] Podman - - [ ] Seatbelt - - [ ] Windows - - [ ] npm run - - [ ] npx - - [ ] Docker - - [ ] Linux - - [ ] npm run - - [ ] npx - - [ ] Docker diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index b9015e6a5fa..a51a12bf1d1 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -775,7 +775,7 @@ export const AppContainer = (props: AppContainerProps) => { if (e instanceof ProjectIdRequiredError) { // OAuth succeeded but account setup requires project ID // Show the error message directly without "Failed to authenticate" prefix - onAuthError(e.message); + onAuthError(getErrorMessage(e)); return; } onAuthError(