{"record":{"id":"34bbc070b088fe9c","repo":"BerriAI/litellm","slug":"tool-call-function-must-be-a-dictionary","errorCode":null,"errorMessage":"Tool call `function` must be a dictionary","messagePattern":"Tool call `function` must be a dictionary","errorType":"validation","errorClass":"OCIError","httpStatus":400,"severity":"error","filePath":"litellm/llms/oci/chat/generic.py","lineNumber":129,"sourceCode":"    )\n\n\ndef adapt_messages_to_generic_oci_standard_tool_call(role: str, tool_calls: list) -> OCIMessage:\n    \"\"\"Convert an assistant tool-call message to OCI format.\"\"\"\n    tool_calls_formatted: Final = []\n    for tool_call in tool_calls:\n        if not isinstance(tool_call, dict):\n            raise OCIError(status_code=400, message=\"Each tool call must be a dictionary\")\n        if tool_call.get(\"type\") != \"function\":\n            raise OCIError(status_code=400, message=\"OCI only supports function tool calls\")\n\n        tool_call_id = tool_call.get(\"id\")\n        if not isinstance(tool_call_id, str):\n            raise OCIError(status_code=400, message=\"Tool call `id` must be a string\")\n\n        tool_function = tool_call.get(\"function\")\n        if not isinstance(tool_function, dict):\n            raise OCIError(status_code=400, message=\"Tool call `function` must be a dictionary\")\n\n        function_name = tool_function.get(\"name\")\n        if not isinstance(function_name, str):\n            raise OCIError(status_code=400, message=\"Tool call `function.name` must be a string\")\n\n        arguments = tool_call[\"function\"].get(\"arguments\", \"{}\")\n        if not isinstance(arguments, str):\n            raise OCIError(\n                status_code=400,\n                message=\"Tool call `function.arguments` must be a JSON string\",\n            )\n\n        tool_calls_formatted.append(\n            OCIToolCall(\n                id=tool_call_id,\n                type=\"FUNCTION\",\n                name=function_name,\n                arguments=arguments,","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/chat/generic.py#L111-L147","documentation":"Inside each tool call dict, the 'function' member must itself be a dictionary containing the tool name and arguments. If 'function' is missing, None, a string, or any non-dict value, OCIError(400) 'Tool call `function` must be a dictionary' is raised during OCI request construction.","triggerScenarios":"Sending tool calls like {'id':'c1','type':'function','function':'get_weather'} or omitting 'function' entirely when calling an oci/ GENERIC model with assistant tool-call history.","commonSituations":"Flattening the function object into sibling keys ({'name':..., 'arguments':...}) by mistake; JSON payloads built from tuples; serializers that drop nested objects on missing data.","solutions":["Nest the descriptor: 'function': {'name': str, 'arguments': json_string}.","When converting from other formats, wrap flat name/arguments into the nested object before sending.","Validate structure with a pre-flight recursive check (see defense)."],"exampleFix":"# before\n{'id':'c1','type':'function','name':'get_weather','arguments':'{}'}\n\n# after\n{'id':'c1','type':'function','function':{'name':'get_weather','arguments':'{}'}}","handlingStrategy":"type-guard","validationCode":"for tc in msg.get('tool_calls') or []:\n    assert isinstance(tc.get('function'), dict), f\"tool call 'function' must be a dict: {tc!r}\"","typeGuard":"def tool_call_has_function_dict(tc: object) -> bool:\n    return isinstance(tc, dict) and isinstance(tc.get('function'), dict)","tryCatchPattern":null,"preventionTips":["Use the exact OpenAI nested layout {'function': {'name', 'arguments'}} everywhere; never flatten.","Write a message-schema unit test that validates the history your app produces."],"tags":["oci","tool-calls","input-validation","structure"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}