BerriAI/litellm · error · ValueError

logging_obj is required

Error message

logging_obj is required

What it means

Thrown by SpeechToCompletionBridgeHandler.validate_input_kwargs when 'logging_obj' is absent from kwargs or is not an instance of litellm.LiteLLMLoggingObj (handler.py:65). The bridge logs the underlying completion call, so a properly constructed logging object is mandatory — a dict or None substitute is rejected.

Source

Thrown at litellm/endpoints/speech/speech_to_completion_bridge/handler.py:65

        optional_params: Final = kwargs.get("optional_params")
        if optional_params is None or not isinstance(optional_params, dict):
            raise ValueError("optional_params is required")

        litellm_params: Final = kwargs.get("litellm_params")
        if litellm_params is None or not isinstance(litellm_params, dict):
            raise ValueError("litellm_params is required")

        headers = kwargs.get("headers")
        if headers is None or not isinstance(headers, dict):
            raise ValueError("headers is required")

        headers = kwargs.get("headers")
        if headers is None or not isinstance(headers, dict):
            raise ValueError("headers is required")

        logging_obj: Final = kwargs.get("logging_obj")
        if logging_obj is None or not isinstance(logging_obj, LiteLLMLoggingObj):
            raise ValueError("logging_obj is required")

        return SpeechToCompletionBridgeHandlerInputKwargs(
            model=model,
            input=input,
            voice=kwargs.get("voice"),
            optional_params=optional_params,
            litellm_params=litellm_params,
            logging_obj=logging_obj,
            custom_llm_provider=custom_llm_provider,
            headers=headers,
        )

    def speech(
        self,
        model: str,
        input: str,
        voice: str | dict | None,
        optional_params: dict,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Route calls through litellm.audio_speech() so the router creates the logging object
  2. If invoking the handler directly, construct one via litellm.litellm_core_utils.litellm_logging.LiteLLMLoggingObj (or LoggingCallbackManager) and pass it
  3. In tests, subclass LiteLLMLoggingObj or use an actual instance rather than a bare Mock

Example fix

# before
handler.speech(model=m, input=i, voice=v, optional_params={}, litellm_params={}, headers={}, logging_obj=None, custom_llm_provider="openai")

# after
from litellm.litellm_core_utils.litellm_logging import LiteLLMLoggingObj
logging_obj = LiteLLMLoggingObj(model=m, messages=[], stream=False, call_type="audio_speech")
handler.speech(model=m, input=i, voice=v, optional_params={}, litellm_params={}, headers={}, logging_obj=logging_obj, custom_llm_provider="openai")
Defensive patterns

Strategy: type-guard

Validate before calling

from litellm.litellm_core_utils.litellm_logging import LiteLLMLoggingObj
if not isinstance(logging_obj, LiteLLMLoggingObj):
    logging_obj = LiteLLMLoggingObj(model=model, messages=[], stream=False, call_type="audio_speech")

Type guard

from litellm.litellm_core_utils.litellm_logging import LiteLLMLoggingObj

def is_valid_logging_obj(obj: object) -> bool:
    return isinstance(obj, LiteLLMLoggingObj)

Try / catch

try:
    handler.speech(..., logging_obj=logging_obj, ...)
except ValueError as e:
    if "logging_obj is required" in str(e):
        logger.error("logging_obj must be a LiteLLMLoggingObj instance; use litellm.audio_speech()")
        raise

Prevention

When it happens

Trigger: Direct invocation of speech_to_completion_bridge_handler.speech() with logging_obj=None or a custom class; passing a mock that does not subclass LiteLLMLoggingObj.

Common situations: Bypassing litellm.audio_speech(); unit tests using unittest.Mock instead of a real or subclassed logging object; older litellm versions where the logging class import path moved.

Related errors


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