linshenkx/prompt-optimizer · error · APIError

${providerErrorMessage}

Error message

${providerErrorMessage}

What it means

While streaming an OpenAI Responses API request, an event arrived that has no 'type' field but a string 'message' — the adapter interprets this as a provider-side error event and throws APIError with 'code: message' if a code string is present.

Source

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

    }

    const stream = await openai.responses.create(responsesConfig)
    let accumulatedContent = ''
    let accumulatedReasoning = ''
    const thinkState = { isInThinkMode: false, buffer: '' }
    const toolCalls = new Map<number, any>()

    for await (const event of stream as any) {
      if (
        event &&
        typeof event === 'object' &&
        !('type' in event) &&
        typeof event.message === 'string'
      ) {
        const providerErrorMessage = typeof event.code === 'string'
          ? `${event.code}: ${event.message}`
          : event.message
        throw new APIError(providerErrorMessage)
      }

      switch (event.type) {
        case 'response.output_text.delta': {
          const delta = event.delta || ''
          if (delta) {
            accumulatedContent += delta
            this.processStreamContentWithThinkTags(delta, callbacks, thinkState)
          }
          break
        }
        case 'response.reasoning_text.delta':
        case 'response.reasoning_summary_text.delta': {
          const delta = event.delta || ''
          if (delta) {
            accumulatedReasoning += delta
            callbacks.onReasoningToken?.(delta)
          }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Capture the SSE frames (code + message) to see the provider's real error (often auth/quota/model issues)
  2. Fix the underlying reported error (key, model name, quota)
  3. If the gateway is yours, emit proper response.error / response.failed typed events
  4. Upgrade the gateway or adapter to a version aligned on the Responses event schema

Example fix

# before (gateway emits)
{"message":"Insufficient credits","code":"billing"}

# after (gateway emits)
{"type":"response.error","error":{"code":"billing","message":"Insufficient credits"}}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function isUntypedStreamErrorEvent(e: any): boolean {
  return e != null && !('type' in e) && typeof e.message === 'string'
}

Try / catch

for await (const chunk of stream) { ... }
// wrap the whole consumption:
try { await consume(adapter.sendMessageStream(msgs)) }
catch (e) {
  if (e instanceof APIError && /^[\w.-]+: /.test(e.message)) showProviderError(e.message)
  else throw e
}

Prevention

When it happens

Trigger: Streaming from an OpenAI-compatible gateway that emits non-standard SSE events (plain {message, code} objects without type), or a mid-stream server error pushed as a message event.

Common situations: Third-party Responses-API emitters that don't fully conform to OpenAI's event schema, gateways translating chat-completions errors mid-stream.

Related errors


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