linshenkx/prompt-optimizer · error · APIError

API error: ${JSON.stringify(error.response.data)}

Error message

API error: ${JSON.stringify(error.response.data)}

What it means

The OpenAI-compatible request failed and the error carried an axios-style error.response.data payload (a structured provider error body). The adapter JSON-stringifies that body into the APIError message so the provider's error detail (code, message) is preserved.

Source

Thrown at packages/core/src/services/llm/adapters/openai-adapter.ts:183

      throw new APIError('Unexpected API response format')
    } catch (error: any) {
      console.error('[OpenAIAdapter] Failed to fetch models:', error)

      // 连接错误处理(包括跨域检测)
      if (error.message && (error.message.includes('Failed to fetch') ||
          error.message.includes('Connection error'))) {
        const isCrossOriginError = this.detectCrossOriginError(error, baseURL)

        if (isCrossOriginError) {
          throw new APIError(`Cross-origin connection failed: ${error.message}`)
        } else {
          throw new APIError(`Connection failed: ${error.message}`)
        }
      }

      // API返回的错误信息
      if (error.response?.data) {
        throw new APIError(`API error: ${JSON.stringify(error.response.data)}`)
      }

      // 其他错误,保持原始信息
      throw new APIError(error.message || 'Unknown error')
    }
  }

  // ===== 参数定义(用于buildDefaultModel) =====

  /**
   * 获取参数定义
   * 基于 OpenAI 官方文档: https://platform.openai.com/docs/api-reference/chat/create
   */
  protected getParameterDefinitions(_modelId: string): readonly ParameterDefinition[] {
    return [
      {
        name: 'reasoning_effort',
        labelKey: 'params.reasoning_effort.label',

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Read the embedded JSON: code/message fields identify the exact provider error
  2. invalid_api_key → fix connectionConfig.apiKey
  3. model_not_found → update the model ID in config
  4. 429/quota → retry with backoff and check billing limits

Example fix

// before
catch (e) { console.log(e.message) } // opaque JSON string

// after
catch (e: any) {
  const m = /API error: (.*)$/.exec(e.message)
  const detail = m ? JSON.parse(m[1]) : null
  if (detail?.code === 'invalid_api_key') refreshKey()
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function parseProviderApiError(e: unknown): { code?: string; message?: string } | null {
  if (!(e instanceof APIError)) return null
  const m = /API error: (.*)$/.exec(e.message)
  try { return m ? JSON.parse(m[1]) : null } catch { return null }
}

Try / catch

try { await adapter.getModelsAsync() }
catch (e) {
  const detail = parseProviderApiError(e)
  if (detail?.code === 'invalid_api_key') return rotateKey()
  if (detail?.code === 'rate_limit_exceeded') return backoffRetry(fn)
  throw e
}

Prevention

When it happens

Trigger: Provider returned 4xx/5xx with a JSON error body: invalid API key, model not found, insufficient quota, context length exceeded — surfaced during getModelsAsync.

Common situations: 401 invalid_api_key, 404 model_not_found after renaming, 429 rate_limit_exceeded, billing/quota exhausted on OpenAI or a compatible gateway.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/c0f5ba176d62f759. Report an issue: GitHub.