BerriAI/litellm · error · CustomLLMError

Not implemented yet!

Error message

Not implemented yet!

What it means

Base CustomLLM.completion raises CustomLLMError(500, 'Not implemented yet!') — it is a stub. Any CustomLLM subclass used for non-streaming sync chat that does not override completion() will hit this. LiteLLM routes custom providers through these methods, so an unimplemented hook surfaces as a 500-style error.

Source

Thrown at litellm/llms/custom_llm.py:64

        self,
        model: str,
        messages: list,
        api_base: str,
        custom_prompt_dict: dict,
        model_response: ModelResponse,
        print_verbose: Callable,
        encoding,
        api_key,
        logging_obj,
        optional_params: dict,
        acompletion=None,
        litellm_params=None,
        logger_fn=None,
        headers={},
        timeout: float | httpx.Timeout | None = None,
        client: HTTPHandler | None = None,
    ) -> Union[ModelResponse, "CustomStreamWrapper"]:
        raise CustomLLMError(status_code=500, message="Not implemented yet!")

    def streaming(
        self,
        model: str,
        messages: list,
        api_base: str,
        custom_prompt_dict: dict,
        model_response: ModelResponse,
        print_verbose: Callable,
        encoding,
        api_key,
        logging_obj,
        optional_params: dict,
        acompletion=None,
        litellm_params=None,
        logger_fn=None,
        headers={},
        timeout: float | httpx.Timeout | None = None,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Override completion() in your CustomLLM subclass returning a ModelResponse
  2. If you only implemented async methods, call with the async API (litellm.acompletion) instead
  3. If you only implemented streaming(), call with stream=True

Example fix

# before
class MyLLM(CustomLLM):
    def streaming(self, *args, **kwargs): ...
# litellm.completion(...) without stream=True -> Not implemented yet!

# after
class MyLLM(CustomLLM):
    def completion(self, *args, **kwargs) -> ModelResponse:
        # build and return ModelResponse
        ...
    def streaming(self, *args, **kwargs): ...
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect
assert type(my_llm).completion is not CustomLLM.completion, "override completion() before non-streaming sync calls"

Type guard

def supports_sync_completion(provider) -> bool:
    from litellm import CustomLLM
    return type(provider).completion is not CustomLLM.completion

Try / catch

try:
    resp = litellm.completion(model="my-provider/model", messages=msgs)
except Exception as e:
    if "Not implemented yet" in str(e):
        raise NotImplementedError("provider lacks completion()") from e
    raise

Prevention

When it happens

Trigger: Registering a CustomLLM subclass (e.g. via custom_provider or litellm.completion with a custom handler) and calling non-streaming completion without the subclass defining completion().

Common situations: Users implement only streaming() and call without stream=True; copy an example CustomLLM that implements acompletion only and use the sync path; refactor removes the method accidentally.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/52caed56877eabfb. Report an issue: GitHub.