From 6ff5a9f76c3e6839a463dde2f760ddf7fc2c0279 Mon Sep 17 00:00:00 2001 From: Mrunmayee Daware <165297479+Mrun25@users.noreply.github.com> Date: Wed, 7 Oct 2026 17:46:22 +0530 Subject: [PATCH] fix: keep is_error from Anthropic tool_result in /v1/messages translation --- .../pass_through/adapters/transformation.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/litellm/llms/anthropic/pass_through/adapters/transformation.py b/litellm/llms/anthropic/pass_through/adapters/transformation.py index 8e0dc83e563..8bf0d43b235 100644 --- a/litellm/llms/anthropic/pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/pass_through/adapters/transformation.py @@ -525,10 +525,13 @@ class LiteLLMAnthropicMessagesAdapter: self._add_cache_control_if_applicable(content, doc_obj, model) new_user_content_list.append(doc_obj) elif content.get("type") == "tool_result": + tool_result_content = self._tool_result_content(content.get("content")) + if content.get("is_error"): + tool_result_content = self._mark_tool_result_as_error(tool_result_content) tool_result = ChatCompletionToolMessage( role="tool", tool_call_id=content.get("tool_use_id", ""), - content=self._tool_result_content(content.get("content")), + content=tool_result_content, ) self._add_cache_control_if_applicable(content, tool_result, model) tool_message_list.append(tool_result) @@ -1317,6 +1320,20 @@ class LiteLLMAnthropicMessagesAdapter: case _: return list(parts) + @staticmethod + def _mark_tool_result_as_error(content: ToolResultContent) -> ToolResultContent: + """Keep Anthropic's `is_error` signal visible. + + Chat Completions tool messages have no error field, so encode the + flag into the content itself; models and downstream provider + mappings can then still tell the tool call failed. + """ + if isinstance(content, str): + return "[tool error] " + content if content else "[tool error]" + if isinstance(content, list): + return [ChatCompletionTextObject(type="text", text="[tool error] "), *content] + return content + def _tool_result_part(self, item: object) -> ToolMessageContentPart | None: if isinstance(item, str): return ChatCompletionTextObject(type="text", text=item)