headroomlabs-ai/headroom · error · NotImplementedError

{self.name} backend does not support OpenAI format

Error message

{self.name} backend does not support OpenAI format

What it means

The default Backend.handle_openai (base.py) raises NotImplementedError for backends that do not implement the OpenAI-compatible chat-completion format. Each backend subclass opts in by overriding the method; calling it on a backend that did not (e.g. a passthrough or native-format-only backend) hits the base stub.

Source

Thrown at headroom/backends/base.py:141

        headers: dict[str, str],
    ) -> BackendResponse:
        """Send an OpenAI-format message request.

        Unlike send_message(), this takes OpenAI-format input and returns
        OpenAI-format output (no Anthropic conversion). Optional - only
        implemented by backends that support OpenAI-compatible APIs.

        Args:
            body: Request body in OpenAI chat completion format.
            headers: Request headers.

        Returns:
            BackendResponse with body in OpenAI chat completion format.

        Raises:
            NotImplementedError: If backend doesn't support OpenAI format.
        """
        raise NotImplementedError(f"{self.name} backend does not support OpenAI format")

    async def stream_openai_message(
        self,
        body: dict[str, Any],
        headers: dict[str, str],
    ) -> AsyncIterator[str]:
        """Stream an OpenAI-format chat completion.

        Yields SSE-formatted strings: 'data: {...}\\n\\n' for each chunk,
        ending with 'data: [DONE]\\n\\n'.

        Args:
            body: Request body in OpenAI chat completion format (stream: true).
            headers: Request headers.

        Yields:
            SSE-formatted strings ready to send to client.

View on GitHub (pinned to 322425c43b)

Solutions

  1. Switch to a backend that supports OpenAI format (the error names the backend via self.name — check that class for which methods it overrides).
  2. If you own the backend subclass, implement handle_openai (and stream_openai_message for streaming) to translate OpenAI bodies to the backend's native format.
  3. If you own the caller, dispatch based on a capability flag instead of assuming every backend speaks OpenAI format.

Example fix

# before
resp = await backend.handle_openai(body, headers)  # NotImplementedError

# after
class MyBackend(Backend):
    async def handle_openai(self, body, headers):
        native = to_native(body)
        return BackendResponse(body=from_native(await self._call(native)))
Defensive patterns

Strategy: type-guard

Validate before calling

from headroom.backends.base import Backend

def supports_openai(backend: Backend) -> bool:
    return type(backend).handle_openai is not Backend.handle_openai

if not supports_openai(backend):
    raise SystemExit(f"{backend.name} cannot serve OpenAI-format requests; pick another backend")

Type guard

def supports_openai_format(b: object) -> bool:
    """True when the backend class overrides the OpenAI-format handler."""
    handle = getattr(type(b), "handle_openai", None)
    return callable(handle) and getattr(handle, "__module__", "") != Backend.__module__ or handle is not Backend.handle_openai

Try / catch

try:
    resp = await backend.handle_openai(body, headers)
except NotImplementedError:
    logger.error("backend %s lacks OpenAI-format support; rerouting", backend.name)
    raise  # or route to a capable backend

Prevention

When it happens

Trigger: Calling backend.handle_openai(body, headers) on a Backend subclass that only implements the native/Anthropic-format methods, or routing OpenAI-format traffic to a backend whose class never overrode the OpenAI-format handler.

Common situations: Adding a new custom Backend subclass and forgetting to implement the OpenAI surface while the proxy front door speaks OpenAI format; pointing an OpenAI client at a backend that only supports its native API.

Related errors


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