{"record":{"id":"9b17ba7b68884515","repo":"BerriAI/litellm","slug":"unable-to-parse-model-max-fallback-depth-exceeded","errorCode":null,"errorMessage":"Unable to parse model, max fallback depth exceeded - received model: {model}","messagePattern":"Unable to parse model, max fallback depth exceeded - received model: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/proxy/auth/auth_checks.py","lineNumber":3544,"sourceCode":") -> Literal[True]:\n    \"\"\"\n    Checks if token can call a given model\n\n    Args:\n        - model: str\n        - llm_router: Optional[Router]\n        - models: List[str]\n        - team_model_aliases: Optional[Dict[str, str]]\n        - object_type: Literal[\"user\", \"team\", \"key\", \"org\"]. We use the object type to raise the correct exception type\n\n    Returns:\n        - True: if token allowed to call model\n\n    Raises:\n        - Exception: If token not allowed to call model\n    \"\"\"\n    if fallback_depth >= DEFAULT_MAX_RECURSE_DEPTH:\n        raise Exception(f\"Unable to parse model, max fallback depth exceeded - received model: {model}\")\n    if isinstance(model, list):\n        for m in model:\n            _can_object_call_model(\n                model=m,\n                llm_router=llm_router,\n                models=models,\n                team_model_aliases=team_model_aliases,\n                team_id=team_id,\n                object_type=object_type,\n                fallback_depth=fallback_depth + 1,\n            )\n        return True\n\n    potential_models: Final = [model]\n    if model in litellm.model_alias_map:\n        potential_models.append(litellm.model_alias_map[model])\n    elif llm_router and model in llm_router.model_group_alias:\n        _model: Final = llm_router._get_model_from_alias(model)","sourceCodeStart":3526,"sourceCodeEnd":3562,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/auth/auth_checks.py#L3526-L3562","documentation":"Raised by the recursive _can_object_call_model() when fallback_depth reaches DEFAULT_MAX_RECURSE_DEPTH (100, overridable via the DEFAULT_MAX_RECURSE_DEPTH env var). The function recurses through model lists and model-alias indirections to check access; hitting the cap means the model reference could not be resolved to a concrete model within 100 hops — practically always a self-referencing alias chain.","triggerScenarios":"A model alias in the router/team_model_aliases that resolves to itself or forms a cycle (alias A -> alias A, or A -> B -> A); deeply nested wildcard/list expansions in a team's models config passed as nested lists; passing a model value whose alias chain never terminates at a deployment.","commonSituations":"Configuring model_group aliases where an alias name equals its upstream model (litellm_params.model pointing at another alias that points back); copy-paste alias configs creating loops; upgrade changes in alias resolution exposing previously latent cycles.","solutions":["Audit model_list and team_model_aliases in config.yaml for circular references — every alias must eventually resolve to a concrete deployment (litellm_params.model of a real provider model)","Rename the alias so it differs from any model/alias it points to; break A->B->A chains by pointing one hop at a concrete model","As a temporary workaround, raise the cap via DEFAULT_MAX_RECURSE_DEPTH env var — but a cycle is a config bug and should be fixed"],"exampleFix":"# before (cycle: alias points at itself)\nmodel_list:\n  - model_name: gpt-4o\n    litellm_params:\n      model: openai/gpt-4o   # NOT the alias name\n# after\nmodel_list:\n  - model_name: my-gpt4o\n    litellm_params:\n      model: openai/gpt-4o","handlingStrategy":"validation","validationCode":"def assert_alias_graph_acyclic(model_list: list[dict]) -> None:\n    names = {m[\"model_name\"] for m in model_list}\n    targets = {m[\"model_name\"]: m[\"litellm_params\"][\"model\"] for m in model_list}\n    for start in names:\n        seen, cur = set(), start\n        while cur in targets:\n            if cur in seen:\n                raise ValueError(f\"model alias cycle at {cur}\")\n            seen.add(cur)\n            cur = targets[cur]","typeGuard":null,"tryCatchPattern":"try:\n    allowed = _can_object_call_model(model, llm_router, models, ...)\nexcept Exception as e:\n    if \"max fallback depth exceeded\" in str(e):\n        raise ValueError(\"Circular/over-nested model alias config\") from e\n    raise","preventionTips":["Never set litellm_params.model to a model_name that (transitively) points back to itself","Lint config.yaml alias graphs in CI; keep model lists flat instead of nested lists"],"tags":["litellm","model-alias","recursion","config","router"],"backgroundTag":"circular-reference","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}