Skip to content

fix(core): keep provider error messages when the payload is a plain string - #352

Open
sonderhq wants to merge 1 commit into
lessweb:mainfrom
sonderhq:fix/preserve-string-provider-error-payloads
Open

sonderhq wants to merge 1 commit into
lessweb:mainfrom
sonderhq:fix/preserve-string-provider-error-payloads

Conversation

@sonderhq

Copy link
Copy Markdown

Problem

getProviderMessage() only accepted an object-shaped error payload, so a provider
or gateway that sends the message as a plain string was silently dropped:

function getProviderMessage(error: unknown): string | undefined {
  if (!isRecord(error) || !isRecord(error.error)) {
    return undefined;
  }
  return safeText(error.error.message);
}

describeLlmError() prefers this provider text over the SDK's message, so when the
payload is a string the fallback wins and the user is shown the generic
HTTP 502: 502 Bad Gateway - the status survives, but the part that says what
actually went wrong (model not found, quota exhausted, key blocked, IP not
allow-listed, ...) is gone. The same text is what lands in the local logs via
getLlmErrorDetails(). Gateways in front of OpenAI-compatible endpoints are the
likely source here: {"error": "Gateway failed"}, or a body that is just a JSON
string.

Fix

getProviderMessage() accepts a string payload as the provider message. The object
shape keeps working exactly as before, and nothing else changes - getLlmErrorDetails()
(the shape used for logs and retry classification) is untouched.

Tests

New test in packages/core/src/tests/llm-error.test.ts. Reproduced first:

not ok 2 - describeLlmError keeps provider errors whose payload is a plain string
  + actual   - expected
  + 'HTTP 502: 502 Bad Gateway [request ID: request-789]'
  - 'HTTP 502: Gateway failed [request ID: request-789]'

After the fix the same error renders HTTP 502: Gateway failed [request ID: request-789].

  • @vegamo/deepcode-core suite: 383 tests, 381 pass, 0 fail, 2 skipped.
    The same suite on the unmodified base is 382 / 380 / 0 / 2 - the only delta is
    the new test, so no neighbouring test moved.
  • npm run typecheck, npm run lint, npm run format:check pass.
Related shape upstream (not part of this change)

A neighbouring agent project treats the same payload shape as a defect: a provider
returning a string error field crashed their step, fixed by normalising
string | object before reading the message (opencode#49338 → opencode#49350). The
semantics here are the same normalisation applied to the error-description path,
where the consequence is a lost message rather than a crash.

…tring

OpenAI-compatible providers and gateways do not all send the error body as an
object: some return the message as a plain string, either as the error field
(`{"error": "Gateway failed"}`) or as the whole JSON body. getProviderMessage
required `error.error` to be a record, so those payloads were discarded and the
user only saw the generic SDK text ("HTTP 502: 502 Bad Gateway") instead of the
provider's own explanation - which is the part that says what to fix (model not
found, quota, blocked key, ...).

Accept a string payload as the provider message; the object shape is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant