{"record":{"id":"c58713a7a7113f49","repo":"BerriAI/litellm","slug":"allowed-callers-must-be-a-list-of-strings","errorCode":null,"errorMessage":"allowed_callers must be a list of strings","messagePattern":"allowed_callers must be a list of strings","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/anthropic/chat/transformation.py","lineNumber":825,"sourceCode":"                    returned_tool[\"defer_loading\"] = _defer_loading_function\n\n        ## check if allowed_callers is set in the tool\n        _allowed_callers: Final = tool.get(\"allowed_callers\", None)\n        _allowed_callers_function: Final = tool.get(\"function\", {}).get(\"allowed_callers\", None)\n        if returned_tool is not None:\n            # Only set allowed_callers on tools that support it (not tool search tools or computer tools)\n            tool_type = returned_tool.get(\"type\", \"\")\n            if tool_type not in (\n                \"tool_search_tool_regex_20251119\",\n                \"tool_search_tool_bm25_20251119\",\n                \"computer_20241022\",\n                \"computer_20250124\",\n            ):\n                if _allowed_callers is not None:\n                    if not isinstance(_allowed_callers, list) or not all(\n                        isinstance(item, str) for item in _allowed_callers\n                    ):\n                        raise ValueError(\"allowed_callers must be a list of strings\")\n                    returned_tool[\"allowed_callers\"] = _allowed_callers\n                elif _allowed_callers_function is not None:\n                    if not isinstance(_allowed_callers_function, list) or not all(\n                        isinstance(item, str) for item in _allowed_callers_function\n                    ):\n                        raise ValueError(\"allowed_callers must be a list of strings\")\n                    returned_tool[\"allowed_callers\"] = _allowed_callers_function\n\n        ## check if input_examples is set in the tool\n        _input_examples: Final = tool.get(\"input_examples\", None)\n        _input_examples_function: Final = tool.get(\"function\", {}).get(\"input_examples\", None)\n        if returned_tool is not None:\n            # Only set input_examples on user-defined tools (type \"custom\" or no type)\n            tool_type = returned_tool.get(\"type\", \"\")\n            if tool_type == \"custom\" or (tool_type == \"\" and \"name\" in returned_tool):\n                if _input_examples is not None and isinstance(_input_examples, list):\n                    returned_tool[\"input_examples\"] = _input_examples\n                elif _input_examples_function is not None and isinstance(_input_examples_function, list):","sourceCodeStart":807,"sourceCodeEnd":843,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/anthropic/chat/transformation.py#L807-L843","documentation":"For tools that support it (not tool-search/computer tools), a top-level 'allowed_callers' must be a list whose every element is a string. Anything else — a string, a dict, a list containing non-strings — raises this ValueError during transformation, before the API call.","triggerScenarios":"Passing allowed_callers: 'user@org' (bare string instead of list), allowed_callers: ['a', 123], or a dict of caller permissions; typical when configuring MCP-style tools with caller restrictions.","commonSituations":"Config files where a single value is written as a scalar instead of a one-element list; caller lists built from user IDs that are ints; merging configs that silently changes the shape.","solutions":["Wrap single values in a list: ['user@org'] and ensure every entry is a string.","Convert numeric IDs: [str(c) for c in allowed_callers].","Validate the shape at config-load time (list of str) with a JSON schema or small helper."],"exampleFix":"# before\n{\"type\": \"custom\", \"name\": \"f\", \"allowed_callers\": \"alice\"}\n\n# after\n{\"type\": \"custom\", \"name\": \"f\", \"allowed_callers\": [\"alice\"]}","handlingStrategy":"validation","validationCode":"ac = tool.get(\"allowed_callers\")\nif isinstance(ac, str):\n    tool[\"allowed_callers\"] = [ac]\nelif isinstance(ac, list):\n    tool[\"allowed_callers\"] = [str(c) for c in ac]","typeGuard":"def allowed_callers_ok(tool) -> bool:\n    ac = tool.get(\"allowed_callers\")\n    return ac is None or (isinstance(ac, list) and all(isinstance(x, str) for x in ac))","tryCatchPattern":null,"preventionTips":["Always wrap a single caller in a list in configs.","str()-cast user IDs before adding them to allowed_callers."],"tags":["anthropic","tools","allowed-callers","type-validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}