From a59ad0e8c63b4159a35558dcae03ed4a7ca42c6f Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 2 Jan 2026 20:02:39 -0500 Subject: [PATCH] fix(minimax): prevent double-resolve race condition and align placeholder - Add resolved flag + safeResolve() wrapper to prevent timeout/response race - Align apiKeyPlaceholder to YOUR_MINIMAX_API_KEY_HERE across presets --- src/api/services/provider-presets.ts | 2 +- src/utils/api-key-validator.ts | 17 ++++++++++++----- ui/src/lib/provider-presets.ts | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/api/services/provider-presets.ts b/src/api/services/provider-presets.ts index 8b1f9b65..82223565 100644 --- a/src/api/services/provider-presets.ts +++ b/src/api/services/provider-presets.ts @@ -105,7 +105,7 @@ export const PROVIDER_PRESETS: ProviderPreset[] = [ baseUrl: 'https://api.minimax.io/anthropic', defaultProfileName: 'mm', defaultModel: 'MiniMax-M2.1', - apiKeyPlaceholder: 'YOUR_MINIMAX_API_KEY', + apiKeyPlaceholder: 'YOUR_MINIMAX_API_KEY_HERE', apiKeyHint: 'Get your API key at platform.minimax.io', category: 'alternative', }, diff --git a/src/utils/api-key-validator.ts b/src/utils/api-key-validator.ts index 6eb5af34..cc67c8ac 100644 --- a/src/utils/api-key-validator.ts +++ b/src/utils/api-key-validator.ts @@ -64,6 +64,13 @@ async function validateProviderKey( } return new Promise((resolve) => { + let resolved = false; + const safeResolve = (result: ValidationResult) => { + if (resolved) return; + resolved = true; + resolve(result); + }; + const isHttps = url.protocol === 'https:'; const httpModule = isHttps ? https : http; const defaultPort = isHttps ? 443 : 80; @@ -83,9 +90,9 @@ async function validateProviderKey( clearTimeout(timeoutId); if (res.statusCode === 200) { - resolve({ valid: true }); + safeResolve({ valid: true }); } else if (res.statusCode === 401 || res.statusCode === 403) { - resolve({ + safeResolve({ valid: false, error: `API key rejected by ${config.displayName}`, suggestion: @@ -100,7 +107,7 @@ async function validateProviderKey( `[CCS-Preflight] Unexpected status ${res.statusCode} from ${url.href} - fail-open` ); } - resolve({ valid: true }); + safeResolve({ valid: true }); } res.resume(); @@ -108,12 +115,12 @@ async function validateProviderKey( req.on('error', () => { clearTimeout(timeoutId); - resolve({ valid: true }); + safeResolve({ valid: true }); }); const timeoutId = setTimeout(() => { req.destroy(); - resolve({ valid: true }); + safeResolve({ valid: true }); }, timeoutMs); req.end(); diff --git a/ui/src/lib/provider-presets.ts b/ui/src/lib/provider-presets.ts index 8e59f017..591260cb 100644 --- a/ui/src/lib/provider-presets.ts +++ b/ui/src/lib/provider-presets.ts @@ -106,7 +106,7 @@ export const PROVIDER_PRESETS: ProviderPreset[] = [ badge: '1M context', defaultModel: 'MiniMax-M2.1', requiresApiKey: true, - apiKeyPlaceholder: 'YOUR_MINIMAX_API_KEY', + apiKeyPlaceholder: 'YOUR_MINIMAX_API_KEY_HERE', apiKeyHint: 'Get your API key at platform.minimax.io', category: 'alternative', },