tirth8205/code-review-graph · error · RuntimeError

OpenAI API returned empty data

Error message

OpenAI API returned empty data

What it means

The OpenAI-compatible provider raises this RuntimeError when a successful response contains no `data` array (or an empty one). Per the OpenAI embeddings spec, data must contain one embedding per input, so an empty result means the gateway silently dropped the request — there is nothing to align, so the provider refuses rather than return wrong-length output.

Source

Thrown at code_review_graph/embeddings.py:520

                            )
                    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
                )
                if all_int_index:
                    expected = set(range(len(texts)))
                    indices = [int(item["index"]) for item in data]

View on GitHub (pinned to b58668751a)

Solutions

  1. Guard calls: skip the API when the input list is empty
  2. If inputs were non-empty, retry the request — the gateway dropped data unexpectedly
  3. Check the gateway/proxy version for known partial-failure bugs

Example fix

# before
vectors = provider.embed(texts)
# after
vectors = provider.embed(texts) if texts else []
Defensive patterns

Strategy: validation

Validate before calling

if not texts:
    return []  # skip the API call entirely
vecs = provider.embed(texts)

Type guard

def safe_embed(provider, texts):
    if not texts:
        return []
    return provider.embed(texts)

Try / catch

try:
    vecs = provider.embed(texts)
except RuntimeError as e:
    if "empty data" in str(e) and texts:
        vecs = provider.embed(texts)  # one retry: gateway hiccup
    else:
        raise

Prevention

When it happens

Trigger: embed()/embed_query() where response.get("data", []) is empty — e.g. an empty input list slipped through, or a compatible gateway returns 200 with no data on partial failure.

Common situations: Calling embed([]) accidentally (empty diff/chunk list), or flaky OpenAI-compatible gateways that omit data under load.

Related errors


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