fix(provider): add recovery guidance for missing OpenAI API key (#616)

This commit is contained in:
Jeevan Mohan Pawar
2026-04-12 17:37:04 +01:00
committed by GitHub
parent 41a86d05fa
commit 9419e8a4a2
2 changed files with 37 additions and 2 deletions

View File

@@ -3,6 +3,9 @@ import { afterEach, expect, test } from 'bun:test'
import { getProviderValidationError } from './providerValidation.ts' import { getProviderValidationError } from './providerValidation.ts'
const originalEnv = { const originalEnv = {
CLAUDE_CODE_USE_OPENAI: process.env.CLAUDE_CODE_USE_OPENAI,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
OPENAI_BASE_URL: process.env.OPENAI_BASE_URL,
CLAUDE_CODE_USE_GEMINI: process.env.CLAUDE_CODE_USE_GEMINI, CLAUDE_CODE_USE_GEMINI: process.env.CLAUDE_CODE_USE_GEMINI,
GEMINI_API_KEY: process.env.GEMINI_API_KEY, GEMINI_API_KEY: process.env.GEMINI_API_KEY,
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY, GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,
@@ -20,6 +23,9 @@ function restoreEnv(key: string, value: string | undefined): void {
} }
afterEach(() => { afterEach(() => {
restoreEnv('CLAUDE_CODE_USE_OPENAI', originalEnv.CLAUDE_CODE_USE_OPENAI)
restoreEnv('OPENAI_API_KEY', originalEnv.OPENAI_API_KEY)
restoreEnv('OPENAI_BASE_URL', originalEnv.OPENAI_BASE_URL)
restoreEnv('CLAUDE_CODE_USE_GEMINI', originalEnv.CLAUDE_CODE_USE_GEMINI) restoreEnv('CLAUDE_CODE_USE_GEMINI', originalEnv.CLAUDE_CODE_USE_GEMINI)
restoreEnv('GEMINI_API_KEY', originalEnv.GEMINI_API_KEY) restoreEnv('GEMINI_API_KEY', originalEnv.GEMINI_API_KEY)
restoreEnv('GOOGLE_API_KEY', originalEnv.GOOGLE_API_KEY) restoreEnv('GOOGLE_API_KEY', originalEnv.GOOGLE_API_KEY)
@@ -71,3 +77,19 @@ test('still errors when no Gemini credential source is available', async () => {
'GEMINI_API_KEY, GOOGLE_API_KEY, GEMINI_ACCESS_TOKEN, or Google ADC credentials are required when CLAUDE_CODE_USE_GEMINI=1.', 'GEMINI_API_KEY, GOOGLE_API_KEY, GEMINI_ACCESS_TOKEN, or Google ADC credentials are required when CLAUDE_CODE_USE_GEMINI=1.',
) )
}) })
test('openai missing key error includes recovery guidance and config locations', async () => {
process.env.CLAUDE_CODE_USE_OPENAI = '1'
process.env.OPENAI_BASE_URL = 'https://api.openai.com/v1'
delete process.env.OPENAI_API_KEY
const message = await getProviderValidationError(process.env)
expect(message).toContain(
'OPENAI_API_KEY is required when CLAUDE_CODE_USE_OPENAI=1 and OPENAI_BASE_URL is not local.',
)
expect(message).toContain(
'set CLAUDE_CODE_USE_OPENAI=0 in your shell environment',
)
expect(message).toContain('Saved startup settings can come from')
expect(message).toContain('.openclaude-profile.json')
})

View File

@@ -1,14 +1,16 @@
import { resolve } from 'node:path'
import { import {
getGithubEndpointType, getGithubEndpointType,
isLocalProviderUrl, isLocalProviderUrl,
resolveCodexApiCredentials, resolveCodexApiCredentials,
resolveProviderRequest, resolveProviderRequest,
} from '../services/api/providerConfig.js' } from '../services/api/providerConfig.js'
import { getGlobalClaudeFile } from './env.js'
import { import {
type GeminiResolvedCredential, type GeminiResolvedCredential,
resolveGeminiCredential, resolveGeminiCredential,
} from './geminiAuth.js' } from './geminiAuth.js'
import { redactSecretValueForDisplay } from './providerProfile.js' import { PROFILE_FILE_NAME, redactSecretValueForDisplay } from './providerProfile.js'
function isEnvTruthy(value: string | undefined): boolean { function isEnvTruthy(value: string | undefined): boolean {
if (!value) return false if (!value) return false
@@ -61,6 +63,17 @@ function checkGithubTokenStatus(
return 'valid' return 'valid'
} }
function getOpenAIMissingKeyMessage(): string {
const globalConfigPath = getGlobalClaudeFile()
const profilePath = resolve(process.cwd(), PROFILE_FILE_NAME)
return [
'OPENAI_API_KEY is required when CLAUDE_CODE_USE_OPENAI=1 and OPENAI_BASE_URL is not local.',
`To recover, run /provider and switch provider, or set CLAUDE_CODE_USE_OPENAI=0 in your shell environment.`,
`Saved startup settings can come from ${globalConfigPath} or ${profilePath}.`,
].join('\n')
}
export async function getProviderValidationError( export async function getProviderValidationError(
env: NodeJS.ProcessEnv = process.env, env: NodeJS.ProcessEnv = process.env,
options?: { options?: {
@@ -137,7 +150,7 @@ export async function getProviderValidationError(
if (useGithub && hasGithubToken) { if (useGithub && hasGithubToken) {
return null return null
} }
return 'OPENAI_API_KEY is required when CLAUDE_CODE_USE_OPENAI=1 and OPENAI_BASE_URL is not local.' return getOpenAIMissingKeyMessage()
} }
return null return null