{"record":{"id":"55dad91d9fb2663b","repo":"BerriAI/litellm","slug":"tool-call-id-must-be-a-string","errorCode":null,"errorMessage":"Tool call `id` must be a string","messagePattern":"Tool call `id` must be a string","errorType":"validation","errorClass":"OCIError","httpStatus":400,"severity":"error","filePath":"litellm/llms/oci/chat/generic.py","lineNumber":125,"sourceCode":"        role=open_ai_to_generic_oci_role_map[role],\n        content=new_content,\n        toolCalls=None,\n        toolCallId=None,\n    )\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(","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/chat/generic.py#L107-L143","documentation":"Each tool call in an assistant message must carry a string 'id' so LiteLLM can map it into OCIToolCall(id=...). A missing, None, or non-string id raises OCIError(400) 'Tool call `id` must be a string' client-side. The id is what later role='tool' messages reference via tool_call_id, so it cannot be omitted.","triggerScenarios":"Hand-constructing assistant tool call history without an 'id' (e.g. {'type':'function','function':{...}}), or with id set to an integer/None, in a request to an oci/ GENERIC model.","commonSituations":"Fabricating synthetic assistant turns for few-shot tool use and forgetting the id; a database schema storing tool calls without ids; trimming ids 'to save tokens' in long conversations.","solutions":["Give every tool call a unique string id and reuse it in the matching tool result's tool_call_id (e.g. 'call_001').","If generating synthetic history, mint ids with uuid4().hex or a counter.","Pre-flight check: all(isinstance(tc.get('id'), str) and tc['id'] for tc in msg['tool_calls'])."],"exampleFix":"# before\n{'type':'function','function':{'name':'f','arguments':'{}'}}\n\n# after\n{'id':'call_001','type':'function','function':{'name':'f','arguments':'{}'}}\n# and the tool reply: {'role':'tool','tool_call_id':'call_001','content':'42'}","handlingStrategy":"validation","validationCode":"import uuid\n\nfor tc in msg.get('tool_calls') or []:\n    if not isinstance(tc.get('id'), str) or not tc['id']:\n        tc['id'] = f'call_{uuid.uuid4().hex[:8]}'","typeGuard":"def tool_call_has_string_id(tc: object) -> bool:\n    return isinstance(tc, dict) and isinstance(tc.get('id'), str) and bool(tc['id'])","tryCatchPattern":null,"preventionTips":["Always pair: each tool_call id gets exactly one matching tool_call_id in the tool reply.","When fabricating synthetic history, generate ids from a counter or uuid and keep them stable in the transcript."],"tags":["oci","tool-calls","input-validation","missing-parameter"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}