{"record":{"id":"37990779766de545","repo":"BerriAI/litellm","slug":"litellm-settings-callbacks-entry-error-entry-r-379907","errorCode":null,"errorMessage":"litellm_settings.callbacks entry '{error.entry}' resolved to {type(error.loaded).__name__} {error.loaded!r}, which is neither a CustomLogger instance nor a callable, so the proxy would never run it.","messagePattern":"litellm_settings\\.callbacks entry '(.+?)' resolved to (.+?) (.+?), which is neither a CustomLogger instance nor a callable, so the proxy would never run it\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/common_utils/callback_utils.py","lineNumber":103,"sourceCode":"    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):\n        _raise_callback_load_error(resolved)\n    return resolved\n\n\ndef initialize_callbacks_on_proxy(\n    value: Any,\n    premium_user: bool,\n    config_file_path: str,","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/common_utils/callback_utils.py#L85-L121","documentation":"Startup ValueError from callback resolution: the litellm_settings.callbacks entry resolved to an object that is neither a CustomLogger instance, a callable, nor even a class - _CallbackNotDispatchable. The message shows the resolved object's type and repr (e.g. a module, a string constant, an int, a dataclass field). The proxy refuses to start because it would silently never run the callback.","triggerScenarios":"Pointing callbacks at a module path ('my_callbacks') instead of an attribute inside it; referencing a module-level variable (DEBUG = True), an imported name that is itself a module, or a typo'd attribute that resolves via importlib to something unexpected.","commonSituations":"Missing the attribute after the last dot; env-conditional definitions where the name is a flag not a logger; packages that expose submodules shadowing intended objects; copy-paste paths from another project whose module layout differs.","solutions":["Point the entry at a concrete object: 'my_callbacks.proxy_handler_instance' (module.instance), not the bare module.","Verify with python -c \"import my_callbacks as m; print(type(m.proxy_handler_instance))\" - it must be a CustomLogger instance or function.","Fix typos in the last path segment; check the attribute actually exists at top level.","If you meant a class, instantiate it at module level first (see the class-entry error)."],"exampleFix":"// before\nlitellm_settings:\n  callbacks: [\"my_callbacks\"]  # module, not an object\n\n// after\nlitellm_settings:\n  callbacks: [\"my_callbacks.proxy_handler_instance\"]","handlingStrategy":"validation","validationCode":"import importlib\n\ndef entry_resolves_to_object(entry: str) -> bool:\n    module_name, _, attr = entry.rpartition('.')\n    if not attr or not module_name:\n        return False  # bare module path\n    try:\n        return hasattr(importlib.import_module(module_name), attr)\n    except ImportError:\n        return False","typeGuard":"def is_valid_callback_entry(entry: object) -> bool:\n    if not isinstance(entry, str) or '.' not in entry:\n        return False\n    module_name, _, attr = entry.rpartition('.')\n    try:\n        obj = getattr(importlib.import_module(module_name), attr)\n    except Exception:\n        return False\n    import types\n    return not isinstance(obj, (types.ModuleType, str, int, float, bool)) and (callable(obj) or hasattr(obj, 'async_post_call_success_hook'))","tryCatchPattern":null,"preventionTips":["Always write callbacks entries as module.attribute, never module alone.","Smoke-test config in a pre-deploy job: import each entry and assert it is an instance/callable.","Keep callback modules free of debug flags that shadow handler names."],"tags":["litellm","proxy","callbacks","config","valueerror"],"backgroundTag":"callback-config-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}