tirth8205/code-review-graph · error · RuntimeError

OpenAI API error

Error message

OpenAI API error: {msg}

What it means

This RuntimeError fires when the HTTP request to the OpenAI-compatible embeddings endpoint succeeded (status 200) but the JSON response body contains a top-level "error" object — some gateways report errors in-band rather than via HTTP status. The provider extracts error.message (or stringifies the error) and raises.

Solutions

  1. Inspect the embedded message to identify the underlying cause (quota, model access, upstream failure)
  2. If using a proxy/router, check its logs and upstream provider configuration
  3. Verify the model name is allowed for your key/gateway
  4. Retry with backoff if the message indicates a transient upstream issue
Defensive patterns

Strategy: try-catch

Validate before calling

# Smoke-test the gateway: some return 200 with in-band errors
provider.embed_query("ping")  # fail fast before a long batch

Try / catch

try:
    vecs = provider.embed(texts)
except RuntimeError as e:
    if "OpenAI API error:" in str(e):
        log_gateway_incident(str(e))  # in-band gateway failure
    raise

Prevention

When it happens

Trigger: embed()/embed_query() receiving a 200 response whose body is {"error": {...}} — typical of OpenAI-compatible proxies, LiteLLM routers, orAzure-style endpoints that wrap upstream failures in-band.

Common situations: Self-hosted or proxied OpenAI-compatible gateways that return 200 with an error payload for quota, model-access, or upstream-provider failures; upstream OpenAI outages surfaced through a router.

Related errors


AI-assisted analysis of tirth8205/code-review-graph@b58668751a (2026-08-28). Data as JSON: /api/errors/dbf491fcdcaef383. Report an issue: GitHub.

Appendix: source

Thrown at code_review_graph/embeddings.py:516

                            err_obj = parsed["error"]
                            err_msg = (
                                err_obj.get("message", err_msg)
                                if isinstance(err_obj, dict) else str(err_obj)
                            )
                    except Exception:  # nosec B110
                        # Non-JSON error body is fine: we already seeded
                        # err_msg with the raw body above, so fall through.
                        pass
                    raise RuntimeError(
                        f"OpenAI API HTTP {http_err.code}: {err_msg}"
                    ) from http_err

                response = _json.loads(raw)

                if "error" in response:
                    err = response["error"]
                    msg = err.get("message", "unknown") if isinstance(err, dict) else str(err)
                    raise RuntimeError(f"OpenAI API error: {msg}")

                data = response.get("data", [])
                if not data:
                    raise RuntimeError("OpenAI API returned empty data")
                # OpenAI spec: data[i].index maps to input[i], but some
                # compatible gateways re-order results or drop entries on
                # partial failure, and others omit `index` entirely. Three
                # disjoint cases:
                #   1. All items have a valid int ``index``: must form a
                #      permutation of 0..N-1, then sort and use.
                #   2. NO item carries an ``index`` field: trust server
                #      order, only verify count matches.
                #   3. Anything in between (partial indices, str indices,
                #      missing on some): refuse. Zipping server order in
                #      that case would happily misalign the indexed items.
                any_has_index = any("index" in item for item in data)
                all_int_index = all(
                    isinstance(item.get("index"), int) for item in data

View on GitHub (pinned to b58668751a)