BerriAI/litellm · error · ValueError
callback_name is required in key_logging
Error message
callback_name is required in key_logging
What it means
Raised while preparing the per-key logging-callback health probe: every entry in the key's 'logging' metadata list must be a dict containing 'callback_name'; an entry without it cannot be mapped to a configured callback, so a ValueError aborts the check. It is raised inside the health-check try block, so the client actually receives it wrapped as 'Key health check failed: callback_name is required in key_logging' with status 500.
Source
Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:6548
"""
Test the key-based logging
- Test that key logging is correctly formatted and all args are passed correctly
- Make a mock completion call -> user can check if it's correctly logged
- Check if any logger.exceptions were triggered -> if they were then returns it to the user client side
"""
import logging
from io import StringIO
from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request
from litellm.proxy.proxy_server import general_settings, proxy_config
logging_callbacks: Final[list[str]] = []
for callback in key_logging:
if callback.get("callback_name") is not None:
logging_callbacks.append(callback["callback_name"])
else:
raise ValueError("callback_name is required in key_logging")
log_capture_string: Final = StringIO()
ch: Final = logging.StreamHandler(log_capture_string)
ch.setLevel(logging.ERROR)
logger: Final = logging.getLogger()
logger.addHandler(ch)
try:
data = {
"model": "openai/litellm-key-health-test",
"messages": [
{
"role": "user",
"content": "Hello, this is a test from litellm /key/health. No LLM API call was made for this",
}
],
}
data = await add_litellm_data_to_request(View on GitHub (pinned to 77b7c6c40c)
Solutions
- Ensure every element of metadata['logging'] includes 'callback_name', e.g. {"callback_name": "litellm.proxy.custom_callbacks.my_handler.MyHandler"}
- Verify the named callback actually appears in proxy_logging_obj's loaded callbacks — otherwise fix config.yaml callback_settings/litellm_settings first
- Update the key's metadata via /key/update rather than recreating the key
- Re-run GET /key/health after fixing; the 500 wrapper disappears once the inner ValueError is gone
Example fix
# before
await client.post('/key/generate', json={
'metadata': {'logging': [{'class': 'my_pkg.MyLogger'}]} # -> 500 Key health check failed: callback_name is required in key_logging
})
# after
await client.post('/key/generate', json={
'metadata': {'logging': [{'callback_name': 'my_pkg.MyLogger'}]}
}) Defensive patterns
Strategy: validation
Validate before calling
def validate_key_logging(logging_entries: list) -> None:
for i, entry in enumerate(logging_entries):
if not isinstance(entry, dict) or not entry.get('callback_name'):
raise ValueError(f"logging[{i}] is missing required 'callback_name'") Type guard
def is_valid_key_logging(entries: object) -> bool:
return (
isinstance(entries, list)
and all(isinstance(e, dict) and isinstance(e.get('callback_name'), str) and e['callback_name'] for e in entries)
) Try / catch
try:
await client.post('/key/generate', json=payload_with_logging_metadata)
except httpx.HTTPStatusError as e:
if 'callback_name is required' in e.response.text:
raise ValueError('fix metadata.logging entries: each needs callback_name') from e
raise Prevention
- Generate logging metadata from a single typed helper that always sets callback_name
- Assert the callback exists in config.yaml callback settings before attaching it to keys
- Run GET /key/health in CI for a sample key to catch metadata problems early
When it happens
Trigger: Setting key metadata like {"logging": [{"class": "my_pkg.MyLogger"}]} or [{"callback_type": "logger"}] with no callback_name; hand-editing metadata JSON and dropping the field; older docs/examples that used a different key name for the callback.
Common situations: Custom callback integrations added via key metadata; migration from older LiteLLM metadata conventions; programmatic metadata assembly that conditionally omits the name.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- mcp_tools_config must be a list of dictionaries
- GitHub source must include 'repo' field (e.g., 'org/repo')
- URL source must include 'url' field (e.g., 'https://github.c
- git-subdir source must include 'url' field (e.g., 'https://g
- git-subdir source must include 'path' field (e.g., 'plugins/
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9ed412038581c219.
Report an issue: GitHub.