BerriAI/litellm · error · ValueError
logging_obj is required
Error message
logging_obj is required
What it means
litellm.create_file requires an initialized LiteLLM logging object passed in kwargs as litellm_logging_obj. It is normally injected by LiteLLM's router/main layer before the function runs; if it is absent (None), the function refuses to proceed because success/failure logging and cost tracking could not work.
Source
Thrown at litellm/files/main.py:164
custom_llm_provider: FileCreateProvider | None = None,
extra_headers: dict[str, str] | None = None,
extra_body: dict[str, str] | None = None,
**kwargs,
) -> OpenAIFileObject | Coroutine[Any, Any, OpenAIFileObject]:
"""
Files are used to upload documents that can be used with features like Assistants, Fine-tuning, and Batch API.
LiteLLM Equivalent of POST: POST https://api.openai.com/v1/files
Specify either provider_list or custom_llm_provider.
"""
try:
_is_async: Final = kwargs.pop("acreate_file", False) is True
optional_params: Final = GenericLiteLLMParams(**kwargs)
litellm_params_dict: Final = dict(**kwargs)
logging_obj: Final = cast(LiteLLMLoggingObj | None, kwargs.get("litellm_logging_obj"))
if logging_obj is None:
raise ValueError("logging_obj is required")
client: Final = kwargs.get("client")
### TIMEOUT LOGIC ###
timeout = optional_params.timeout or kwargs.get("request_timeout", 600) or 600
# set timeout for 10 minutes by default
if (
timeout is not None
and isinstance(timeout, httpx.Timeout)
and supports_httpx_timeout(cast(str, custom_llm_provider)) is False
):
read_timeout: Final = timeout.read or 600
timeout = read_timeout # default 10 min timeout
elif timeout is not None and not isinstance(timeout, httpx.Timeout):
timeout = float(timeout)
elif timeout is None:
timeout = 600.0
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Call the public API: litellm.create_file(file=..., purpose='fine-tune'|'batch'|'assistants', custom_llm_provider='openai') — it sets up logging for you
- If you must call create_file directly, pass a logging object: from litellm.litellm_core_utils.litellm_logging import Logging; kwargs['litellm_logging_obj'] = Logging(model, stream=False, call_type='apass_through_endpoint')
- Check that nothing in your wrapper pops or filters litellm_logging_obj out of kwargs before the call
Example fix
# before
from litellm.files.main import create_file
resp = create_file(file=open('f.jsonl','rb'), purpose='batch', custom_llm_provider='openai')
# after
import litellm
resp = litellm.create_file(file=open('f.jsonl','rb'), purpose='batch', custom_llm_provider='openai') Defensive patterns
Strategy: validation
Validate before calling
kwargs.setdefault("litellm_logging_obj", None)
if kwargs["litellm_logging_obj"] is None and "litellm_logging_obj" not in kwargs:
# call public API instead; it injects the logger
import litellm # use litellm.create_file(...) Type guard
def has_logging_obj(kwargs: dict) -> bool:
lo = kwargs.get("litellm_logging_obj")
return lo is not None and hasattr(lo, "update_from_kwargs") Prevention
- Never import litellm.files.main.create_file directly; use litellm.create_file
- In wrappers, forward **kwargs untouched
When it happens
Trigger: Calling litellm.files.main.create_file (or the internal acreate_file path) directly instead of through the public litellm.create_file API, so kwargs never contain litellm_logging_obj; or a custom fork/wrapper that strips kwargs before delegating.
Common situations: Users importing internal modules to bypass the public API; mocking tests that call create_file with hand-built kwargs; upgrades that changed the internal kwarg plumbing while code called private entry points.
Related errors
- litellm_logging_obj is required, but got None
- logging_obj is required
- logging_obj is required
- File content stream does not support sync iteration
- File content stream does not support async iteration
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/30ad8d1164aba5be.
Report an issue: GitHub.