BerriAI/litellm · error · ValueError

logging_obj is required

Error message

logging_obj is required

What it means

validate_input_kwargs raises when 'logging_obj' is missing or is not a LiteLLMLoggingObj. The bridge needs the logging object for success/failure logging and to recover raw SSE data when the completed response has empty output. It is created by litellm's logging pipeline in every supported entry point.

Source

Thrown at litellm/completion_extras/litellm_responses_transformation/handler.py:138

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

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

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

        model_response: Final = typed_kwargs.get("model_response")
        if model_response is None or not isinstance(model_response, ModelResponse):
            raise ValueError("model_response is required")

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

        return ResponsesToCompletionBridgeHandlerInputKwargs(
            model=model,
            messages=messages,
            optional_params=optional_params,
            litellm_params=litellm_params,
            headers=headers,
            model_response=model_response,
            logging_obj=logging_obj,
            custom_llm_provider=custom_llm_provider,
            encoding=typed_kwargs.get("encoding"),
        )

    def completion(
        self, *args, **kwargs
    ) -> Union[
        Coroutine[Any, Any, Union["ModelResponse", "CustomStreamWrapper"]],
        "ModelResponse",

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Call litellm.completion/acompletion which generates the logging object automatically
  2. If direct, create one via litellm.litellm_core_utils.litellm_logging.LoggingHandler / LiteLLMLoggingObj before invoking
  3. Do not strip logging_obj when wrapping the pipeline; pass it through unchanged

Example fix

# before
kwargs = {..., "logging_obj": None}

# after
from litellm.litellm_core_utils.litellm_logging import LoggingHandler
logger = LoggingHandler(model="gpt-4o", messages=msgs, stream=False, litellm_call_id="x", function_id="y")
kwargs = {..., "logging_obj": logger}
Defensive patterns

Strategy: validation

Validate before calling

def has_logging_obj(kwargs: dict) -> bool:
    return kwargs.get("logging_obj") is not None and hasattr(kwargs["logging_obj"], "post_call")

Type guard

def is_logging_obj(v) -> bool:
    import litellm
    return isinstance(v, litellm.LiteLLMLoggingObj)

Prevention

When it happens

Trigger: Calling the bridge handler without logging_obj, or passing a mock/None; disabling logging in a fork by dropping the key instead of passing a no-op logger.

Common situations: Direct handler use; test doubles that bypass generate_base_llm_response; custom proxies that strip logging objects.

Related errors


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