RestApiTool crashes the agent run on a non-UTF-8 error response body (UnicodeDecodeError in the HTTPStatusError handler)
还没有人认领这个 Issue。
评估
调研方向
从 RestApiTool.call() 开始,将 HTTPStatusError 处理器与下面几行处的非 JSON 成功路径进行比较。使用模拟的非 UTF-8 响应添加提到的回归测试,然后验证工具返回预期的 404 错误 dict,并且 agent 运行不会失败。
由索引模型根据 Issue 内容生成。
描述
🔴 Required Information
Describe the Bug:
When an API call fails, RestApiTool.call() builds the error message for the model with:
except httpx.HTTPStatusError:
error_details = response.content.decode("utf-8")
That forces UTF-8 regardless of the charset the server declares. A non-UTF-8 error body raises UnicodeDecodeError, for example a Latin-1/Windows-1252 page from an older ERP or IIS server, a message with accented characters, or a binary body. The exception is raised inside the except handler, so the sibling except ValueError can't catch it. It propagates out of the tool and ends the whole agent run, so the model never sees the HTTP error it could have recovered from.
Steps to Reproduce:
pip install google-adk(reproduced onmain@ 3f4bb8fa).- Run the script below: a real
RunnerplusLlmAgentplusOpenAPIToolset, with a mocked model and anhttpx.MockTransportbackend that answers404with atext/plain; charset=iso-8859-1body.
Expected Behavior:
The tool returns its usual error dict, decoded with the declared charset:
... Execution Error: Status Code: 404, Commande introuvable : échec
Observed Behavior:
RUN FAILED: UnicodeDecodeError - 'utf-8' codec can't decode byte 0xe9 in position 23: invalid continuation byte
Environment Details:
- ADK Library Version (pip show google-adk):
main@ 3f4bb8fa - Desktop OS: Windows 11
- Python Version (python -V): 3.12.10
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A (mocked model; the bug is in response handling)
🟡 Optional Information
Minimal Reproduction Code:
import asyncio
import httpx
from google.adk.agents.llm_agent import LlmAgent
from google.adk.models.base_llm import BaseLlm
from google.adk.models.llm_response import LlmResponse
from google.adk.runners import InMemoryRunner
from google.adk.tools.openapi_tool.openapi_spec_parser.openapi_toolset import OpenAPIToolset
from google.genai import types
spec = {
"openapi": "3.0.0",
"info": {"title": "Legacy ERP", "version": "1"},
"servers": [{"url": "https://erp.example.com"}],
"paths": {"/orders/{id}": {"get": {
"operationId": "getOrder",
"parameters": [{"name": "id", "in": "path", "required": True, "schema": {"type": "string"}}],
"responses": {"200": {"description": "ok"}},
}}},
}
def handler(request: httpx.Request):
# A legacy server answering in Windows-1252 / Latin-1, as it declares.
return httpx.Response(
404,
content="Commande introuvable : échec".encode("latin-1"),
headers={"content-type": "text/plain; charset=iso-8859-1"},
)
class FakeModel(BaseLlm):
model: str = "fake"
calls: int = 0
async def generate_content_async(self, llm_request, stream=False):
self.calls += 1
part = (types.Part.from_function_call(name="get_order", args={"id": "A-42"})
if self.calls == 1 else types.Part.from_text(text="done"))
yield LlmResponse(content=types.Content(role="model", parts=[part]))
agent = LlmAgent(
name="erp_agent",
model=FakeModel(),
tools=[OpenAPIToolset(
spec_dict=spec,
httpx_client_factory=lambda: httpx.AsyncClient(transport=httpx.MockTransport(handler)),
)],
)
async def main():
runner = InMemoryRunner(agent=agent)
session = await runner.session_service.create_session(app_name=runner.app_name, user_id="u")
try:
async for event in runner.run_async(
user_id="u", session_id=session.id,
new_message=types.Content(role="user", parts=[types.Part(text="order A-42?")])):
for fr in event.get_function_responses():
print("function_response:", fr.response)
except Exception as e:
print("RUN FAILED:", type(e).__name__, "-", e)
asyncio.run(main())
Suggested fix: use response.text, which is what the non-JSON success path a few lines below already uses. It decodes with the response's declared charset and replaces undecodable bytes instead of raising. I have a PR ready with a test.
How often has this issue occurred?:
- Always (100%): any non-UTF-8 error body.
- 主要语言
- Python
- 星标
- 21.6k
- 派生
- 4k
- 平均合并
- 13 小时 49 分钟
- 30 天内合并 PR
- 10
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
google/adk-python 的其他 Issue
-
mcp
难度 2/5 1-3 小时 新手友好度 75/100
google/adk-python#7217 · 2 条评论 · 已指派 1 人 ·
-
tools
难度 2/5 1-3 小时 新手友好度 86/100
google/adk-python#7205 · 1 条评论 · 已指派 1 人 ·
-
mcp
难度 2/5 1-3 小时 新手友好度 78/100
google/adk-python#7196 · 1 条评论 · 已指派 1 人 ·
-
eval request clarification
难度 1/5 1-3 小时 新手友好度 86/100
google/adk-python#7146 · 2 条评论 · 已指派 1 人 ·
-
mcp
难度 2/5 1-3 小时 新手友好度 88/100
google/adk-python#7144 · 1 条评论 · 已指派 1 人 ·
查看 google/adk-python 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 88/100
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 78/100
-
enhancement
难度 2/5 1-3 小时 新手友好度 72/100
-
难度 2/5 1-3 小时 新手友好度 74/100