{"record":{"id":"52caed56877eabfb","repo":"BerriAI/litellm","slug":"not-implemented-yet","errorCode":null,"errorMessage":"Not implemented yet!","messagePattern":"Not implemented yet!","errorType":"http","errorClass":"CustomLLMError","httpStatus":500,"severity":"error","filePath":"litellm/llms/custom_llm.py","lineNumber":64,"sourceCode":"        self,\n        model: str,\n        messages: list,\n        api_base: str,\n        custom_prompt_dict: dict,\n        model_response: ModelResponse,\n        print_verbose: Callable,\n        encoding,\n        api_key,\n        logging_obj,\n        optional_params: dict,\n        acompletion=None,\n        litellm_params=None,\n        logger_fn=None,\n        headers={},\n        timeout: float | httpx.Timeout | None = None,\n        client: HTTPHandler | None = None,\n    ) -> Union[ModelResponse, \"CustomStreamWrapper\"]:\n        raise CustomLLMError(status_code=500, message=\"Not implemented yet!\")\n\n    def streaming(\n        self,\n        model: str,\n        messages: list,\n        api_base: str,\n        custom_prompt_dict: dict,\n        model_response: ModelResponse,\n        print_verbose: Callable,\n        encoding,\n        api_key,\n        logging_obj,\n        optional_params: dict,\n        acompletion=None,\n        litellm_params=None,\n        logger_fn=None,\n        headers={},\n        timeout: float | httpx.Timeout | None = None,","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/custom_llm.py#L46-L82","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Override completion() in your CustomLLM subclass returning a ModelResponse","If you only implemented async methods, call with the async API (litellm.acompletion) instead","If you only implemented streaming(), call with stream=True"],"exampleFix":"# before\nclass MyLLM(CustomLLM):\n    def streaming(self, *args, **kwargs): ...\n# litellm.completion(...) without stream=True -> Not implemented yet!\n\n# after\nclass MyLLM(CustomLLM):\n    def completion(self, *args, **kwargs) -> ModelResponse:\n        # build and return ModelResponse\n        ...\n    def streaming(self, *args, **kwargs): ...","handlingStrategy":"type-guard","validationCode":"import inspect\nassert type(my_llm).completion is not CustomLLM.completion, \"override completion() before non-streaming sync calls\"","typeGuard":"def supports_sync_completion(provider) -> bool:\n    from litellm import CustomLLM\n    return type(provider).completion is not CustomLLM.completion","tryCatchPattern":"try:\n    resp = litellm.completion(model=\"my-provider/model\", messages=msgs)\nexcept Exception as e:\n    if \"Not implemented yet\" in str(e):\n        raise NotImplementedError(\"provider lacks completion()\") from e\n    raise","preventionTips":["Add a startup smoke test per custom provider covering each call mode (sync/async x stream/non-stream) you use","Keep the implemented-hook matrix in the provider's docstring"],"tags":["custom-llm","stub","not-implemented","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}