BerriAI/litellm · error · OCIError
OCI only supports function tool calls
Error message
OCI only supports function tool calls
What it means
OCI GENERIC only implements function tool calls, so each tool_call object in an assistant message must have type == "function". Any other type (or missing type, which compares != "function") raises OCIError 400 in adapt_messages_to_generic_oci_standard_tool_call. The whitelist mirrors OCI's FUNCTION-only tool-call surface.
Solutions
- Ensure every tool_call has "type": "function" alongside id and function fields
- Strip non-function tool calls from history before sending to OCI (they can't be represented)
- When rebuilding trimmed histories, preserve all keys or re-serialize from the original response object
- Log offending tool_call objects at build time to catch dropped keys early
Example fix
# before
{"role": "assistant", "tool_calls": [{"id": "1", "function": {"name": "f"}}]} # type missing
# after
{"role": "assistant", "tool_calls": [{"id": "1", "type": "function", "function": {"name": "f", "arguments": "{}"}}]} Defensive patterns
Strategy: validation
Validate before calling
def normalize_tool_call_types(tool_calls: list) -> list:
return [tc for tc in tool_calls if isinstance(tc, dict) and tc.get("type") == "function"] Type guard
def is_function_tool_call(tc) -> bool:
return isinstance(tc, dict) and tc.get("type") == "function" Prevention
- When trimming history, whitelist keys (id, type, function) instead of blacklisting
- Strip provider-specific tool types (code_interpreter etc.) before forwarding history to OCI
When it happens
Trigger: Assistant history containing {"type":"code_interpreter",...} or tool-call objects missing the type key, sent to an oci/generic.* model. Note that a missing `type` also triggers this (None != "function"), so partially-built objects fail here too.
Common situations: Porting agent histories from OpenAI with code_interpreter/retrieval/function variants; trimming tool_call dicts (dropping type) when compressing context; merging tool schemas from multiple providers; custom tool-call types invented by frameworks.
Related errors
- Each tool call must be a dictionary
- Message `tool_calls` must be a list
- OCI only supports function tools
- Tool call `function.arguments` must be a JSON string
- Tool call `function` must be a dictionary
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/a0c2048c40ad593b.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/oci/chat/generic.py:121
)
new_content.append(OCIImageContentPart(imageUrl=OCIImageUrl(url=image_url)))
return OCIMessage(
role=open_ai_to_generic_oci_role_map[role],
content=new_content,
toolCalls=None,
toolCallId=None,
)
def adapt_messages_to_generic_oci_standard_tool_call(role: str, tool_calls: list) -> OCIMessage:
"""Convert an assistant tool-call message to OCI format."""
tool_calls_formatted: Final = []
for tool_call in tool_calls:
if not isinstance(tool_call, dict):
raise OCIError(status_code=400, message="Each tool call must be a dictionary")
if tool_call.get("type") != "function":
raise OCIError(status_code=400, message="OCI only supports function tool calls")
tool_call_id = tool_call.get("id")
if not isinstance(tool_call_id, str):
raise OCIError(status_code=400, message="Tool call `id` must be a string")
tool_function = tool_call.get("function")
if not isinstance(tool_function, dict):
raise OCIError(status_code=400, message="Tool call `function` must be a dictionary")
function_name = tool_function.get("name")
if not isinstance(function_name, str):
raise OCIError(status_code=400, message="Tool call `function.name` must be a string")
arguments = tool_call["function"].get("arguments", "{}")
if not isinstance(arguments, str):
raise OCIError(
status_code=400,
message="Tool call `function.arguments` must be a JSON string",View on GitHub (pinned to 77b7c6c40c)