litellm - ✅(Solved) Fix [Bug]: OpenRouter + GPT-5.4/GPT-5.3-Codex tool calls fail with "expected "function"; function: expected object, received undefined" [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#23803Fetched 2026-04-08 00:49:03
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×3cross-referenced ×2referenced ×2

Error Message

{ "error": { "message": "litellm.BadRequestError: OpenrouterException - {"error":{"message":"3.type: Invalid input: expected \"function\"; 3.function: Invalid input: expected object, received undefined","code":400,"metadata":{"provider_name":"OpenAI"}},"user_id":"org_..."}. Received Model Group=gpt-5.4\nAvailable Model Group Fallbacks=None", "type": null, "param": null, "code": "400" } }

Fix Action

Fixed

PR fix notes

PR #23823: fix(openrouter): prevent extra_body tools from overwriting processed tools

Description (problem / solution / changelog)

Bug Description

When using LiteLLM Proxy with OpenRouter as the provider for GPT-5.4 (also reproducible with GPT-5.3-Codex), any request that includes function/tool definitions fails with a 400 error from OpenRouter/OpenAI.

The error indicates that the tools array contains a malformed entry — specifically, the item at index 3 has type that is not "function" and function field is undefined.

Root Cause

In OpenrouterConfig.transform_request(), the extra_body dictionary was being merged into the response via response.update(extra_body). If extra_body contained a tools key (with stale or malformed data), it would overwrite the correctly processed tools from the parent transform_request method.

Fix

Remove tools from extra_body before updating the response to ensure the correctly processed tools are preserved.

Changes

  • Modified litellm/llms/openrouter/chat/transformation.py to pop tools from extra_body before merging
  • Added regression test in tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py

Testing

  • All 103 OpenRouter tests pass
  • New regression test verifies that malformed tools in extra_body don't overwrite valid tools

Fixes #23803

Changed files

  • litellm/llms/openrouter/chat/transformation.py (modified, +4/-0)
  • tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py (modified, +83/-0)

Code Example

{
  "error": {
    "message": "litellm.BadRequestError: OpenrouterException - {\"error\":{\"message\":\"3.type: Invalid input: expected \\\"function\\\"; 3.function: Invalid input: expected object, received undefined\",\"code\":400,\"metadata\":{\"provider_name\":\"OpenAI\"}},\"user_id\":\"org_...\"}. Received Model Group=gpt-5.4\nAvailable Model Group Fallbacks=None",
    "type": null,
    "param": null,
    "code": "400"
  }
}

---

litellm.BadRequestError: OpenrouterException - {"error":{"message":"3.type: Invalid input: expected "function"; 3.function: Invalid input: expected object, received undefined","code":400,"metadata":{"provider_name":"OpenAI"}},"user_id":"org_..."}. Received Model Group=gpt-5.4
Available Model Group Fallbacks=None
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

When using LiteLLM Proxy with OpenRouter as the provider for gpt-5.4 (also reproducible with gpt-5.3-codex), any request that includes function/tool definitions fails with a 400 error from OpenRouter/OpenAI.

The error indicates that the tools array contains a malformed entry — specifically, the item at index 3 has type that is not "function" and function field is undefined.

Error message:

{
  "error": {
    "message": "litellm.BadRequestError: OpenrouterException - {\"error\":{\"message\":\"3.type: Invalid input: expected \\\"function\\\"; 3.function: Invalid input: expected object, received undefined\",\"code\":400,\"metadata\":{\"provider_name\":\"OpenAI\"}},\"user_id\":\"org_...\"}. Received Model Group=gpt-5.4\nAvailable Model Group Fallbacks=None",
    "type": null,
    "param": null,
    "code": "400"
  }
}

Expected behavior: LiteLLM should correctly serialize all tool definitions in the tools array when proxying to OpenRouter, ensuring every entry has type: "function" and a valid function object. This works fine when calling OpenAI directly.

Notes:

• The 3. prefix in the error indicates it's the 4th tool (0-indexed) in the array that's malformed • Same issue occurs with both gpt-5.4 and gpt-5.3-codex via OpenRouter • Sending the same request directly to OpenAI (not via OpenRouter) works fine • This may be related to LiteLLM's tool serialization when routing through OpenRouter, possibly inserting a null/empty entry or incorrectly transforming the tools array

Steps to Reproduce

  1. Set up LiteLLM Proxy with OpenRouter provider:
  2. Use CodeX with gpt-5.4
  3. Observe: 400 error with expected "function" / expected object, received undefined

Relevant log output

litellm.BadRequestError: OpenrouterException - {"error":{"message":"3.type: Invalid input: expected "function"; 3.function: Invalid input: expected object, received undefined","code":400,"metadata":{"provider_name":"OpenAI"}},"user_id":"org_..."}. Received Model Group=gpt-5.4
Available Model Group Fallbacks=None

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.82.0

Twitter / LinkedIn details

No response

extent analysis

Fix Plan

To resolve the issue with LiteLLM Proxy and OpenRouter, we need to ensure that the tools array is correctly serialized when proxying to OpenRouter. The error indicates that the 4th tool in the array (index 3) has a malformed entry.

Here are the steps to fix the issue:

  • Check the tool definitions in the tools array and ensure that each entry has a type field set to "function" and a valid function object.
  • Verify that the tools array is not being modified or transformed incorrectly when routing through OpenRouter.
  • Update the LiteLLM Proxy code to correctly serialize the tools array when proxying to OpenRouter.

Example code snippet to validate the tools array:

def validate_tools_array(tools):
    for i, tool in enumerate(tools):
        if tool['type'] != 'function' or not tool.get('function'):
            raise ValueError(f"Malformed tool entry at index {i}: {tool}")
    return tools
  • Use this function to validate the tools array before proxying the request to OpenRouter.

Verification

To verify that the fix worked, send a request with the updated tools array and check that the response does not contain a 400 error. You can also log the tools array before and after serialization to ensure that it is being correctly transformed.

Extra Tips

  • Ensure that the LiteLLM Proxy version is up-to-date, as this issue may have been fixed in a later version.
  • If the issue persists, try logging the entire request and response to identify any other potential issues with the serialization or deserialization of the tools array.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - ✅(Solved) Fix [Bug]: OpenRouter + GPT-5.4/GPT-5.3-Codex tool calls fail with "expected "function"; function: expected object, received undefined" [1 pull requests, 1 participants]