headroomlabs-ai/headroom · error · ConnectionError

OpenAI API error: {e}

Error message

OpenAI API error: {e}

What it means

Inside OpenAIEmbedder._embed_with_retry's retry loop, transient errors (APIConnectionError, APITimeoutError, RateLimitError) are retried with exponential backoff, but any other exception hits this branch and is immediately wrapped in ConnectionError('OpenAI API error: {e}') with the original chained. It means a non-retryable client- or request-level failure: bad request, authentication, invalid model, content filter, etc.

Source

Thrown at headroom/memory/adapters/embedders.py:699

                    model=self._model_name,
                    input=texts,
                )
                # Extract embeddings in order
                embeddings = [np.array(item.embedding, dtype=np.float32) for item in response.data]
                return embeddings

            except (APIConnectionError, APITimeoutError, RateLimitError) as e:
                last_error = e
                delay = self.RETRY_DELAY_BASE * (2**attempt)
                logger.warning(
                    f"OpenAI API error (attempt {attempt + 1}/{self._max_retries}): {e}. "
                    f"Retrying in {delay:.1f}s..."
                )
                await asyncio.sleep(delay)

            except Exception as e:
                # Non-retryable error
                raise ConnectionError(f"OpenAI API error: {e}") from e

        # All retries exhausted
        raise ConnectionError(
            f"OpenAI API failed after {self._max_retries} retries: {last_error}"
        ) from last_error

    async def embed(self, text: str) -> np.ndarray:
        """Generate an embedding for a single text.

        Args:
            text: The text to embed.

        Returns:
            Normalized embedding vector as float32 numpy array.

        Raises:
            ConnectionError: If API call fails after retries.
        """

View on GitHub (pinned to 322425c43b)

Solutions

  1. Read the chained original exception (__cause__) — it carries the HTTP status and OpenAI error message that names the real problem.
  2. Fix the model name: stick to text-embedding-3-small / text-embedding-3-large unless the account supports others.
  3. Chunk or truncate very long inputs before embedding; check per-item token counts.
  4. Verify the API key's project/org has embedding access; test with curl if unsure.
  5. Do NOT retry this error class — it is non-retryable by design.

Example fix

# before
await embedder.embed(huge_doc)  # ConnectionError: OpenAI API error: ... maximum context length ...

# after
text = huge_doc[:8000]  # chunk/truncate to model token limit
await embedder.embed(text)
Defensive patterns

Strategy: try-catch

Validate before calling

MAX_TOKENS = 8191  # text-embedding-3-small per-request limit

def embeddable(text: str) -> bool:
    """Cheap pre-check: non-empty and under the model token ceiling."""
    return bool(text.strip()) and len(text) // 4 < MAX_TOKENS  # ~4 chars/token heuristic

Try / catch

try:
    vec = await embedder.embed(text)
except ConnectionError as e:
    if "OpenAI API error" in str(e) and not isinstance(e.__cause__, tuple(map(type, ()) )):
        pass
# simpler and explicit:
try:
    vec = await embedder.embed(text)
except ConnectionError as e:
    cause = e.__cause__
    if type(cause).__name__ in {"BadRequestError", "AuthenticationError", "NotFoundError", "PermissionDeniedError"}:
        log.error("non-retryable: %s", cause); raise
    raise

Prevention

When it happens

Trigger: Calling embed()/embed_batch() when the OpenAI API returns 400/401/403/404/422 — e.g. unknown embedding model name, wrong API key permissions, input text exceeding token limits, or filtered content. Anything not classified as connection/timeout/rate-limit lands here on the first attempt.

Common situations: Model name typo like 'text-embedding-3-large ' (trailing space) or a deprecated model after OpenAI sunsets it; org without access to the embedding model; a single oversized document in a batch; key valid but from a project with restricted endpoints.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/a3a19b0d8bad47af. Report an issue: GitHub.