{"record":{"id":"faf0a0a95680939d","repo":"BerriAI/litellm","slug":"litellm-settings-callbacks-entry-error-entry-r","errorCode":null,"errorMessage":"litellm_settings.callbacks entry '{error.entry}' resolved to the class {error.loaded.__module__}.{error.loaded.__qualname__}, which is neither a CustomLogger instance nor a callable, so the proxy would never run it. Point it at an instance instead, e.g. add `proxy_handler_instance = {error.loaded.__name__}()` to {module_path} and set `callbacks: [\"{module_path}.proxy_handler_instance\"]`.","messagePattern":"litellm_settings\\.callbacks entry '(.+?)' resolved to the class (.+?)\\.(.+?), which is neither a CustomLogger instance nor a callable, so the proxy would never run it\\. Point it at an instance instead, e\\.g\\. add `proxy_handler_instance = (.+?)\\(\\)` to (.+?) and set `callbacks: \\[\"(.+?)\\.proxy_handler_instance\"\\]`\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/common_utils/callback_utils.py","lineNumber":95,"sourceCode":"    Decide whether what a ``litellm_settings.callbacks`` dotted path resolved to can be dispatched.\n\n    A dotted path only ever runs as a ``CustomLogger`` instance or as a callback function. Anything\n    else (most commonly a class instead of an instance) used to load without complaint and then be\n    skipped on every request, with no log line and no error.\n    \"\"\"\n    if isinstance(loaded, CustomLogger) or (callable(loaded) and not isinstance(loaded, type)):\n        return loaded\n    if isinstance(loaded, type):\n        return _CallbackResolvedToClass(entry=entry, loaded=loaded)\n    return _CallbackNotDispatchable(entry=entry, loaded=loaded)\n\n\ndef _raise_callback_load_error(error: _CallbackLoadError) -> NoReturn:\n    \"\"\"The one edge that raises: map a load error onto config load's failure contract.\"\"\"\n    match error:\n        case _CallbackResolvedToClass():\n            module_path: Final = error.entry.rsplit(\".\", 1)[0] if \".\" in error.entry else error.entry\n            raise ValueError(\n                f\"litellm_settings.callbacks entry '{error.entry}' resolved to the class \"\n                f\"{error.loaded.__module__}.{error.loaded.__qualname__}, which is neither a \"\n                \"CustomLogger instance nor a callable, so the proxy would never run it.\"\n                f\" Point it at an instance instead, e.g. add `proxy_handler_instance = {error.loaded.__name__}()` to \"\n                f'{module_path} and set `callbacks: [\"{module_path}.proxy_handler_instance\"]`.'\n            )\n        case _CallbackNotDispatchable():\n            raise ValueError(\n                f\"litellm_settings.callbacks entry '{error.entry}' resolved to \"\n                f\"{type(error.loaded).__name__} {error.loaded!r}, which is neither a \"\n                \"CustomLogger instance nor a callable, so the proxy would never run it.\"\n            )\n    assert_never(error)\n\n\ndef _loaded_callback_or_raise(entry: str, loaded: object) -> CustomLogger | Callable[..., object]:\n    resolved: Final = _classify_loaded_callback(entry=entry, loaded=loaded)\n    if isinstance(resolved, _CallbackResolvedToClass | _CallbackNotDispatchable):","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/common_utils/callback_utils.py#L77-L113","documentation":"Startup ValueError from callback resolution: a litellm_settings.callbacks entry resolved to a Python class object (isinstance(loaded, type)) rather than a CustomLogger instance or a callable. _classify_loaded_callback deliberately rejects classes (calling the class would create an instance at an unpredictable time), and _raise_callback_load_error tells you to point the entry at a module-level instance instead. The message names the exact entry, the class, and the module to fix.","triggerScenarios":"Configuring callbacks: ['my_callbacks.MyCustomLogger'] where MyCustomLogger is declared with class MyCustomLogger(CustomLogger) and never instantiated. The dotted path is imported successfully, but the attribute found is the class object itself.","commonSituations":"Writing a first custom logger and following intuition ('point at the class'); refactoring a module so a former instance is now a class; copying example configs that show class names; name collisions where the instance and class share a name and the class wins.","solutions":["Instantiate at module level in my_callbacks.py: proxy_handler_instance = MyCustomLogger().","Reference the instance in config: callbacks: ['my_callbacks.proxy_handler_instance'].","Alternatively expose any plain function (functions are callable and accepted): def my_hook(kwargs): ... ; callbacks: ['my_callbacks.my_hook'].","Restart the proxy after fixing; this fails fast at config load."],"exampleFix":"// before (my_callbacks.py)\nclass MyCustomLogger(CustomLogger):\n    ...\n# config.yaml: litellm_settings: callbacks: [\"my_callbacks.MyCustomLogger\"]\n\n// after (my_callbacks.py)\nclass MyCustomLogger(CustomLogger):\n    ...\nproxy_handler_instance = MyCustomLogger()\n# config.yaml: litellm_settings: callbacks: [\"my_callbacks.proxy_handler_instance\"]","handlingStrategy":"validation","validationCode":"import importlib\nfrom litellm.integrations.custom_logger import CustomLogger\n\ndef validate_callback_entries(entries):\n    for entry in entries:\n        module_name, _, attr = entry.rpartition('.')\n        obj = getattr(importlib.import_module(module_name), attr)\n        assert not isinstance(obj, type), f'{entry} is a class; point at an instance'\n        assert isinstance(obj, CustomLogger) or callable(obj), f'{entry} is not dispatchable'","typeGuard":"def is_dispatchable_callback(entry: str) -> bool:\n    module_name, _, attr = entry.rpartition('.')\n    try:\n        obj = getattr(importlib.import_module(module_name), attr)\n    except Exception:\n        return False\n    return isinstance(obj, CustomLogger) or (callable(obj) and not isinstance(obj, type))","tryCatchPattern":null,"preventionTips":["Convention: every custom-logger module exposes a module-level instance named proxy_handler_instance.","Run the config validator in CI (litellm --config config.yaml --test or a small importlib check).","Prefer function hooks when possible - plain functions always pass the callable check."],"tags":["litellm","proxy","callbacks","config","valueerror","custom-logger"],"backgroundTag":"callback-config-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}