From 264c7aceaacbe37a9cf5ed1f93ca08ea35bee626 Mon Sep 17 00:00:00 2001 From: Adib234 <30782825+Adib234@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:13:28 -0500 Subject: [PATCH] fix(core): resolve crash in ClearcutLogger when os.cpus() is empty (#19555) --- .../clearcut-logger/clearcut-logger.test.ts | 22 +++++++++++++++++++ .../clearcut-logger/clearcut-logger.ts | 11 ++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.test.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.test.ts index a5bed404d9..c5a00bc11d 100644 --- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.test.ts +++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.test.ts @@ -43,6 +43,7 @@ import { InstallationManager } from '../../utils/installationManager.js'; import si from 'systeminformation'; import type { Systeminformation } from 'systeminformation'; +import * as os from 'node:os'; interface CustomMatchers { toHaveMetadataValue: ([key, value]: [EventMetadataKey, string]) => R; @@ -120,6 +121,7 @@ vi.mock('node:os', async (importOriginal) => { return { ...actual, cpus: vi.fn(() => [{ model: 'Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz' }]), + availableParallelism: vi.fn(() => 8), totalmem: vi.fn(() => 32 * 1024 * 1024 * 1024), }; }); @@ -438,6 +440,26 @@ describe('ClearcutLogger', () => { }); }); + it('handles empty os.cpus() gracefully', async () => { + const { logger, loggerConfig } = setup({}); + vi.mocked(os.cpus).mockReturnValueOnce([]); + + await logger?.logStartSessionEvent(new StartSessionEvent(loggerConfig)); + + const event = logger?.createLogEvent(EventNames.API_ERROR, []); + const metadata = event?.event_metadata[0]; + + const cpuInfoEntry = metadata?.find( + (m) => m.gemini_cli_key === EventMetadataKey.GEMINI_CLI_CPU_INFO, + ); + expect(cpuInfoEntry).toBeUndefined(); + + const cpuCoresEntry = metadata?.find( + (m) => m.gemini_cli_key === EventMetadataKey.GEMINI_CLI_CPU_CORES, + ); + expect(cpuCoresEntry?.value).toBe('8'); + }); + type SurfaceDetectionTestCase = { name: string; env: Record; diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts index a6a8b6d228..d0407aa0d6 100644 --- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts +++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts @@ -615,14 +615,17 @@ export class ClearcutLogger { // Add hardware information only to the start session event const cpus = os.cpus(); - data.push( - { + if (cpus && cpus.length > 0) { + data.push({ gemini_cli_key: EventMetadataKey.GEMINI_CLI_CPU_INFO, value: cpus[0].model, - }, + }); + } + + data.push( { gemini_cli_key: EventMetadataKey.GEMINI_CLI_CPU_CORES, - value: cpus.length.toString(), + value: os.availableParallelism().toString(), }, { gemini_cli_key: EventMetadataKey.GEMINI_CLI_RAM_TOTAL_GB,