Skip to content

Background responses failures lack a stable code/name that maps to an exception class #3212

@adnanboz

Description

@adnanboz

Confirm this is a feature request for the Python library and not the underlying OpenAI API.

  • This is a feature request for the Python library

Describe the feature or improvement you're requesting

When the Responses API runs in background mode (background=True) and a run terminates in status="failed" (or status="incomplete"), the SDK does not surface a stable, machine-readable identifier that callers can map to an existing exception class.

The failure payload looks like:

{
  "status": "failed",
  "error": { "code": "server_error", "message": "..." },
  "incomplete_details": null
}

The HTTP poll itself returns 200 OK, so the SDK's status-code dispatcher is never invoked and no typed exception is raised. The only signal of what kind of failure occurred is the free-form error.code string, which:

  • is not documented as a stable enum,
  • does not correspond 1:1 to any SDK exception class (server_errorInternalServerError, rate_limit_exceededRateLimitError, etc.),
  • is not guaranteed to be present or non-null for every failure mode (e.g. incomplete runs surface their reason in incomplete_details.reason instead, with yet another vocabulary),
  • and may carry values not enumerated anywhere the SDK or callers can rely on.

What exists today (synchronous mode)

For synchronous calls there is a clean, code-driven mapping in openai/_client.py keyed on HTTP status code:

def _make_status_error(self, err_msg, *, body, response):
    data = body.get("error", body) if is_mapping(body) else body
    if response.status_code == 400: return BadRequestError(...)
    if response.status_code == 401: return AuthenticationError(...)
    if response.status_code == 403: return PermissionDeniedError(...)
    if response.status_code == 404: return NotFoundError(...)
    if response.status_code == 409: return ConflictError(...)
    if response.status_code == 422: return UnprocessableEntityError(...)
    if response.status_code == 429: return RateLimitError(...)
    if response.status_code >= 500: return InternalServerError(...)
    return APIStatusError(...)

So the synchronous path has a fully deterministic, documented contract: HTTP code → exception class. The background path has no equivalent — neither in the response body (no stable code) nor in the SDK (no dispatcher).

Why this matters

In synchronous mode the SDK gives us a clean contract. In background mode the same root cause surfaces only as an opaque string with no contract. Any retry/backoff logic built around isinstance(e, InternalServerError) or isinstance(e, RateLimitError) simply cannot work for background runs, even though those are exactly the conditions where retry would be most useful.

Suggested feature

Either:

  1. Add a stable, documented field to background-run failure payloads (e.g. error.type or error.class) whose values directly correspond to existing SDK exception classes — e.g. internal_server_error, rate_limit_error, bad_request_error, content_filter_error, etc. The SDK can then mechanically map this field to the right exception class, mirroring what _make_status_error does today for HTTP status codes.

  2. Or: publish a documented, versioned mapping from each possible error.code / incomplete_details.reason value to the SDK exception class (or "no class") and to a retryable flag. Treat it as part of the public API contract.

Either approach gives background runs the same deterministic contract synchronous calls already enjoy.

Environment

  • openai Python SDK version: <fill in>
  • API: POST /v1/responses with background=true, polled via GET /v1/responses/{id}

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions