headroomlabs-ai/headroom · error · ValueError

openai_api_key is required for OpenAI embedder

Error message

openai_api_key is required for OpenAI embedder

What it means

Choosing the OpenAI embedder requires an API key, and the factory validates this BEFORE consulting the process-wide embedder cache (the cache key is (backend, model) and omits the key, so a cached instance could otherwise mask a missing key for a later caller). ValueError is raised when config.embedder_backend is OPENAI and config.openai_api_key is falsy.

Source

Thrown at headroom/memory/factory.py:169

    sentence-transformers / ONNX model-load cost more than once.

    Args:
        config: Memory system configuration.

    Returns:
        An Embedder implementation based on config.embedder_backend.

    Raises:
        ValueError: If the embedder backend is not supported.
    """

    # Validate inputs ahead of the cache. The cache key is
    # ``(backend, model)`` and intentionally does NOT include the API
    # key — but that means a cached OpenAI embedder would shadow the
    # config-validation step for a subsequent caller who forgot to pass
    # ``openai_api_key``. Run the validation up front instead.
    if config.embedder_backend == EmbedderBackend.OPENAI and not config.openai_api_key:
        raise ValueError("openai_api_key is required for OpenAI embedder")

    key = (
        config.embedder_backend.value
        if hasattr(config.embedder_backend, "value")
        else str(config.embedder_backend),
        config.embedder_model or "",
        # The Ollama backend is built with ``base_url=config.ollama_base_url``,
        # so two configs that share a backend and model but point at different
        # Ollama servers must NOT share a cached embedder — otherwise the second
        # caller silently gets an embedder bound to the first server. (The
        # ``openai_api_key`` omission is handled by the up-front validation
        # above; ``ollama_base_url`` has no such guard and would just resolve to
        # the wrong host.)
        config.ollama_base_url or "",
    )

    with _EMBEDDER_CACHE_LOCK:
        cached = _EMBEDDER_CACHE.get(key)

View on GitHub (pinned to 322425c43b)

Solutions

  1. Pass the key explicitly: MemoryConfig(embedder_backend=EmbedderBackend.OPENAI, embedder_model="text-embedding-3-small", openai_api_key=os.environ["OPENAI_API_KEY"])
  2. Confirm the env var is actually visible to the process (print(bool(os.environ.get('OPENAI_API_KEY')))) — it is not picked up implicitly
  3. If you intended local embeddings, use EmbedderBackend.SENTENCE_TRANSFORMERS or OLLAMA instead of OPENAI

Example fix

# before
config = MemoryConfig(embedder_backend=EmbedderBackend.OPENAI)

# after
import os
config = MemoryConfig(
    embedder_backend=EmbedderBackend.OPENAI,
    openai_api_key=os.environ["OPENAI_API_KEY"],
)
Defensive patterns

Strategy: validation

Validate before calling

if config.embedder_backend == EmbedderBackend.OPENAI and not config.openai_api_key:
    raise RuntimeError("OPENAI_API_KEY not set; cannot use OpenAI embedder")
system = await create_memory_system(config)

Type guard

def openai_embedder_ready(cfg: MemoryConfig) -> bool:
    return cfg.embedder_backend != EmbedderBackend.OPENAI or bool(cfg.openai_api_key)

Try / catch

try:
    system = await create_memory_system(config)
except ValueError as e:
    if "openai_api_key is required" in str(e):
        fail_startup("missing OpenAI key for embedder")
    raise

Prevention

When it happens

Trigger: MemoryConfig(embedder_backend=EmbedderBackend.OPENAI) with openai_api_key unset/None/empty, passed to create_memory_system; or the OPENAI_API_KEY env var was expected but never read (the config field does not auto-populate from env in this path).

Common situations: Dev machine has OPENAI_API_KEY exported but the config object was built without it; key set in a .env file that was never loaded; CI secret missing; key string accidentally whitespace-empty.

Related errors


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