Duplicate check
AgentOS version or commit
2026.8.29
Area
CLI
Reproduction steps
Execute this minimal reproduction script using httpx mock transport or an endpoint that returns a 302 without a Location header:
python
import asyncio
import httpx
from unittest.mock import patch
from agentos.tools.builtin.media import _fetch_image_url
Mock a server returning a 302 without a Location header
class MockTransport(httpx.AsyncBaseTransport):
async def handle_async_request(self, request):
return httpx.Response(302, headers={}, request=request)
async def main():
client = httpx.AsyncClient(transport=MockTransport())
with patch("httpx.AsyncClient", return_value=client):
await _fetch_image_url("https://example.com/test.png")
asyncio.run(main())
Expected behavior
When a redirect status code (301, 302, 303, 307, 308) is received without a Location header, the function should raise a descriptive ToolError:
text
ToolError("Redirect response from https://example.com/test.png missing Location header")
Actual behavior
The function calls await resp.aclose() on line 309, then breaks out of the loop and attempts to iterate over the closed response on line 323 (async for chunk in resp.aiter_bytes(65_536)), crashing with an internal StreamClosed error:
text
Traceback (most recent call last):
File "src/agentos/tools/builtin/media.py", line 323, in _fetch_image_url
async for chunk in resp.aiter_bytes(65_536):
...
httpx.StreamClosed: The stream has been closed.
During handling of the above exception, another exception occurred:
agentos.tools.types.ToolError: Failed to fetch image from URL: The stream has been closed.
Environment
OS: Windows 10 Pro Education (10.0.18362.0) / Linux Ubuntu Python Runtime: Python 3.12+ (tested on Python 3.14.3)
Duplicate check
AgentOS version or commit
2026.8.29
Area
CLI
Reproduction steps
Execute this minimal reproduction script using httpx mock transport or an endpoint that returns a 302 without a Location header:
python
import asyncio
import httpx
from unittest.mock import patch
from agentos.tools.builtin.media import _fetch_image_url
Mock a server returning a 302 without a Location header
class MockTransport(httpx.AsyncBaseTransport):
async def handle_async_request(self, request):
return httpx.Response(302, headers={}, request=request)
async def main():
client = httpx.AsyncClient(transport=MockTransport())
with patch("httpx.AsyncClient", return_value=client):
await _fetch_image_url("https://example.com/test.png")
asyncio.run(main())
Expected behavior
When a redirect status code (301, 302, 303, 307, 308) is received without a Location header, the function should raise a descriptive ToolError:
text
ToolError("Redirect response from https://example.com/test.png missing Location header")
Actual behavior
The function calls await resp.aclose() on line 309, then breaks out of the loop and attempts to iterate over the closed response on line 323 (async for chunk in resp.aiter_bytes(65_536)), crashing with an internal StreamClosed error:
text
Traceback (most recent call last):
File "src/agentos/tools/builtin/media.py", line 323, in _fetch_image_url
async for chunk in resp.aiter_bytes(65_536):
...
httpx.StreamClosed: The stream has been closed.
During handling of the above exception, another exception occurred:
agentos.tools.types.ToolError: Failed to fetch image from URL: The stream has been closed.
Environment
OS: Windows 10 Pro Education (10.0.18362.0) / Linux Ubuntu Python Runtime: Python 3.12+ (tested on Python 3.14.3)