From 9e43189475a0bee5ac5abcbf7ca4b18cd01dc6f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 16 Oct 2026 16:56:54 +0000 Subject: [PATCH] fix: trim WEB_SEARCH_PROVIDER env value Every other environment parser (agentRunTimeoutMsFromEnv, firstNonEmptyEnvValue, slackUsers) trims surrounding whitespace, but webSearchProvider matched the raw value exactly. A .env entry with a trailing space such as `WEB_SEARCH_PROVIDER=parallel ` therefore crashed startup with a confusing validation error. Trim the value before matching, consistent with the other parsers, and treat a blank/whitespace-only value as unset (defaulting to parallel). Adds regression coverage for whitespace handling. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_015a2if6nJJ2D6ZQGjiLGknv --- src/server/parallel.ts | 13 ++++++++++--- tests/parallel.test.ts | 5 +++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/server/parallel.ts b/src/server/parallel.ts index cf6f6131..177b2b0c 100644 --- a/src/server/parallel.ts +++ b/src/server/parallel.ts @@ -9,9 +9,16 @@ export interface WebConfig { parallelApiKey?: string; } export function webSearchProvider(value?: string): WebSearchProvider { - if (!value) return 'parallel'; - if (value === 'parallel' || value === 'browser' || value === 'disabled') - return value; + // Tolerate surrounding whitespace from .env files, matching the other + // environment parsers; a blank value falls back to the default. + const normalized = value?.trim(); + if (!normalized) return 'parallel'; + if ( + normalized === 'parallel' || + normalized === 'browser' || + normalized === 'disabled' + ) + return normalized; throw new Error( 'WEB_SEARCH_PROVIDER must be parallel, browser, or disabled.', ); diff --git a/tests/parallel.test.ts b/tests/parallel.test.ts index 82e79e9e..44c682b1 100644 --- a/tests/parallel.test.ts +++ b/tests/parallel.test.ts @@ -40,6 +40,11 @@ describe('Parallel research', () => { expect(webSearchProvider('disabled')).toBe('disabled'); expect(() => webSearchProvider('other')).toThrow('WEB_SEARCH_PROVIDER'); }); + it('tolerates surrounding whitespace from .env values', () => { + expect(webSearchProvider(' browser ')).toBe('browser'); + expect(webSearchProvider('disabled\n')).toBe('disabled'); + expect(webSearchProvider(' ')).toBe('parallel'); + }); it('searches, extracts and grounds a topic-only brief without a browser', async () => { mcp.callTool .mockResolvedValueOnce(result(page(), page('https://example.org')))