From fd72a8c40fa92cd4edd3b743b84097b92732112f Mon Sep 17 00:00:00 2001 From: joshualitt Date: Fri, 6 Feb 2026 13:33:13 -0800 Subject: [PATCH] bug(core): Ensure storage is initialized early, even if config is not. (#18471) --- integration-tests/resume_repro.responses | 1 + integration-tests/resume_repro.test.ts | 42 +++++++++++++++++++++++ packages/cli/src/gemini.tsx | 6 ++++ packages/cli/src/gemini_cleanup.test.tsx | 2 ++ packages/cli/src/test-utils/mockConfig.ts | 1 + 5 files changed, 52 insertions(+) create mode 100644 integration-tests/resume_repro.responses create mode 100644 integration-tests/resume_repro.test.ts diff --git a/integration-tests/resume_repro.responses b/integration-tests/resume_repro.responses new file mode 100644 index 0000000000..682f3fc9ff --- /dev/null +++ b/integration-tests/resume_repro.responses @@ -0,0 +1 @@ +{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Session started."}],"role":"model"},"finishReason":"STOP","index":0}]}]} diff --git a/integration-tests/resume_repro.test.ts b/integration-tests/resume_repro.test.ts new file mode 100644 index 0000000000..6d4f849886 --- /dev/null +++ b/integration-tests/resume_repro.test.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { TestRig } from './test-helper.js'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +describe('resume-repro', () => { + let rig: TestRig; + + beforeEach(() => { + rig = new TestRig(); + }); + + afterEach(async () => await rig.cleanup()); + + it('should be able to resume a session without "Storage must be initialized before use"', async () => { + const responsesPath = path.join(__dirname, 'resume_repro.responses'); + await rig.setup('should be able to resume a session', { + fakeResponsesPath: responsesPath, + }); + + // 1. First run to create a session + await rig.run({ + args: 'hello', + }); + + // 2. Second run with --resume latest + // This should NOT fail with "Storage must be initialized before use" + const result = await rig.run({ + args: ['--resume', 'latest', 'continue'], + }); + + expect(result).toContain('Session started'); + }); +}); diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx index 494b857656..1e0f4ecd06 100644 --- a/packages/cli/src/gemini.tsx +++ b/packages/cli/src/gemini.tsx @@ -510,6 +510,12 @@ export async function main() { projectHooks: settings.workspace.settings.hooks, }); loadConfigHandle?.end(); + + // Initialize storage immediately after loading config to ensure that + // storage-related operations (like listing or resuming sessions) have + // access to the project identifier. + await config.storage.initialize(); + adminControlsListner.setConfig(config); if (config.isInteractive() && config.storage && config.getDebugMode()) { diff --git a/packages/cli/src/gemini_cleanup.test.tsx b/packages/cli/src/gemini_cleanup.test.tsx index c62cc3fbdd..17e3380f2c 100644 --- a/packages/cli/src/gemini_cleanup.test.tsx +++ b/packages/cli/src/gemini_cleanup.test.tsx @@ -77,6 +77,7 @@ vi.mock('./config/config.js', () => ({ getSandbox: vi.fn(() => false), getQuestion: vi.fn(() => ''), isInteractive: () => false, + storage: { initialize: vi.fn().mockResolvedValue(undefined) }, } as unknown as Config), parseArguments: vi.fn().mockResolvedValue({}), isDebugMode: vi.fn(() => false), @@ -195,6 +196,7 @@ describe('gemini.tsx main function cleanup', () => { getEnableHooks: vi.fn(() => false), getHookSystem: () => undefined, initialize: vi.fn(), + storage: { initialize: vi.fn().mockResolvedValue(undefined) }, getContentGeneratorConfig: vi.fn(), getMcpServers: () => ({}), getMcpClientManager: vi.fn(), diff --git a/packages/cli/src/test-utils/mockConfig.ts b/packages/cli/src/test-utils/mockConfig.ts index 012ad09312..777db91364 100644 --- a/packages/cli/src/test-utils/mockConfig.ts +++ b/packages/cli/src/test-utils/mockConfig.ts @@ -20,6 +20,7 @@ export const createMockConfig = (overrides: Partial = {}): Config => setTerminalBackground: vi.fn(), storage: { getProjectTempDir: vi.fn().mockReturnValue('/tmp/gemini-test'), + initialize: vi.fn().mockResolvedValue(undefined), }, getDebugMode: vi.fn(() => false), getProjectRoot: vi.fn(() => '/'),