litellm - 💡(How to fix) Fix [Bug]: `/v1/responses` can replay `chatcmpl-*` message IDs into OpenAI Responses during cross-provider handoffs [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#27333Fetched 2026-05-07 03:33:07
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Code Example

Claude via LiteLLM -> OpenAI Responses model

---

chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11

---

Invalid 'input[1].id': 'chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11'. Expected an ID that begins with 'msg'.

---

if responses_api_provider_config is None or use_chat_completions_api is True:
    return litellm_completion_transformation_handler.response_api_handler(...)

---

ResponsesAPIResponse(id=chat_completion_response.id, ...)
GenericResponseOutputItem(type="message", id=chat_completion_response.id, ...)

---

{
  "type": "message",
  "id": "chatcmpl-...",
  "role": "assistant",
  "content": [...]
}

---

top-level response id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11
output[0].id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11
forwarded input[0].id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11

---

{
  "model": "gpt-4.1-mini",
  "input": [
    {
      "type": "message",
      "role": "user",
      "content": [{ "type": "input_text", "text": "..." }]
    },
    {
      "type": "message",
      "id": "chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11",
      "role": "assistant",
      "content": [{ "type": "output_text", "text": "..." }]
    }
  ]
}

---

{
  "type": "message",
  "role": "assistant",
  "content": [{ "type": "output_text", "text": "..." }]
}

---

{
  "type": "message",
  "id": "msg_<generated>",
  "role": "assistant",
  "content": [{ "type": "output_text", "text": "..." }]
}

---
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?

Check for existing issues

Related, but I do not think these are the same bug:

  • #26167: bridged Anthropic /v1/responses multi-turn tool calls fail with previous_response_id session reconstruction. This looks adjacent, but the failure here is live in-memory history being replayed into native OpenAI Responses.
  • #16215: OpenAI Responses API support for the Anthropic experimental adapter.
  • #14991: OpenAI rejects invalid Responses item ID namespaces for reasoning items.
  • #26927 and #26012: provider-specific thinking/reasoning cleanup, not message ID normalization.

What happened?

We hit this in an agent workflow that switches providers inside one runner execution:

Claude via LiteLLM -> OpenAI Responses model

The previous assistant message from the Claude/LiteLLM side is kept in memory and then sent to the OpenAI Responses-backed agent. That assistant item still has a Chat Completions-style ID:

chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11

OpenAI Responses rejects the request:

Invalid 'input[1].id': 'chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11'. Expected an ID that begins with 'msg'.

This is specific to the live handoff path. If history is persisted and later reloaded by a storage layer that drops id, the same conversation can avoid the failure.

What I checked

I checked current upstream before filing this:

  • Public main: 934ecdca78daf7ec9514efd47df77bf7495c822d
  • GitHub default branch tip at the time of checking: f318ef03bd8e10b2fe6f694b71fa46bc86ee0d3b

The same relevant behavior appears to be present in both.

Anthropic does not appear to have a native Responses provider config in ProviderConfigManager._get_python_responses_api_config. That method returns native Responses configs for OpenAI, Azure, xAI, GitHub Copilot, ChatGPT, LiteLLM Proxy, VolcEngine, Manus, Perplexity, Databricks GPT models, OpenRouter, and hosted vLLM, but I did not see Anthropic there.

When no native Responses provider config exists, litellm.responses() routes through the Chat Completions bridge:

if responses_api_provider_config is None or use_chat_completions_api is True:
    return litellm_completion_transformation_handler.response_api_handler(...)

In that bridge, the Chat Completions response ID is reused as the Responses object ID and as the output message item ID:

ResponsesAPIResponse(id=chat_completion_response.id, ...)
GenericResponseOutputItem(type="message", id=chat_completion_response.id, ...)

So bridged Claude/Anthropic output can be shaped like this:

{
  "type": "message",
  "id": "chatcmpl-...",
  "role": "assistant",
  "content": [...]
}

The OpenAI Responses transformer validates pydantic/dict shape, but I did not find anything that strips or rewrites an incompatible message item ID before forwarding to OpenAI.

I also checked the transform locally without making a live provider call:

top-level response id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11
output[0].id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11
forwarded input[0].id: chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11

Expected behavior

LiteLLM should not put provider-native IDs into Responses fields that native OpenAI validates with OpenAI-specific ID prefixes.

Any of these would solve the issue:

  • When converting Chat Completions output to Responses-shaped output, generate a Responses-compatible message item ID such as msg_* instead of reusing chatcmpl-*.
  • When forwarding a native OpenAI /v1/responses request, strip invalid input[*].id values from type: "message" items.
  • Keep the original provider ID only in metadata/hidden/internal fields.

The narrower compatibility expectation is: bridged non-OpenAI Responses output should be safe to reuse as Responses input for an OpenAI model for normal message history.

Suggested regression test

One focused regression test would cover this:

  1. Construct a ModelResponse with id="chatcmpl-...".
  2. Convert it through LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response.
  3. Reuse the resulting output message item as input to OpenAIResponsesAPIConfig.transform_responses_api_request.
  4. Assert that the forwarded OpenAI Responses input does not contain an invalid chatcmpl-* input[*].id on a type: "message" item.

Proposed fix

I think the cleanest fix is probably:

  • Use Responses-compatible item IDs for message output generated by the Chat Completions bridge, for example msg_<uuid>.
  • Keep original provider IDs in hidden/internal metadata if needed.
  • Add a final outbound Responses sanitizer before native provider calls that strips invalid IDs from message input items.

Additional context

I am not asking LiteLLM to provide full OpenAI Responses semantic parity for Anthropic/Claude. This is a narrower interop issue: the Responses facade should not emit or forward provider-native IDs in public Responses fields that OpenAI later validates as OpenAI Responses IDs.

Steps to Reproduce

  1. The production path we saw:

  2. Run an agent backed by Claude through LiteLLM.

  3. During the same in-memory runner execution, hand off to an agent backed by an OpenAI Responses model such as gpt-4.1-mini.

  4. Preserve prior assistant message history across the handoff.

  5. Send that history to /v1/responses.

  6. OpenAI rejects the prior assistant item ID if it is chatcmpl-*.

The problematic request shape is roughly:

{
  "model": "gpt-4.1-mini",
  "input": [
    {
      "type": "message",
      "role": "user",
      "content": [{ "type": "input_text", "text": "..." }]
    },
    {
      "type": "message",
      "id": "chatcmpl-dfa2da3a-1586-4ff7-b64e-f59c692a5d11",
      "role": "assistant",
      "content": [{ "type": "output_text", "text": "..." }]
    }
  ]
}

The assistant item should either omit id:

{
  "type": "message",
  "role": "assistant",
  "content": [{ "type": "output_text", "text": "..." }]
}

or use a Responses-compatible ID:

{
  "type": "message",
  "id": "msg_<generated>",
  "role": "assistant",
  "content": [{ "type": "output_text", "text": "..." }]
}

Relevant log output

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.81.14

Twitter / LinkedIn details

No response

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…

FAQ

Expected behavior

LiteLLM should not put provider-native IDs into Responses fields that native OpenAI validates with OpenAI-specific ID prefixes.

Any of these would solve the issue:

  • When converting Chat Completions output to Responses-shaped output, generate a Responses-compatible message item ID such as msg_* instead of reusing chatcmpl-*.
  • When forwarding a native OpenAI /v1/responses request, strip invalid input[*].id values from type: "message" items.
  • Keep the original provider ID only in metadata/hidden/internal fields.

The narrower compatibility expectation is: bridged non-OpenAI Responses output should be safe to reuse as Responses input for an OpenAI model for normal message history.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING