Skip to content

Async client raises UnboundLocalError when a non-streaming response body read fails #459

Description

@Harsh23Kashyap

When the aiohttp read of a non-streaming response body fails (e.g. the connection drops mid-read), the async path raises UnboundLocalError: local variable 'content' referenced before assignment instead of a meaningful SDK error.

In APIRequestor._interpret_async_response (src/together/abstract/api_requestor.py), the except aiohttp.ClientError branch logs the error and falls through:

try:
    content = await result.read()
except (aiohttp.ServerTimeoutError, asyncio.TimeoutError) as e:
    raise error.Timeout("Request timed out") from e
except aiohttp.ClientError as e:
    utils.log_warn(e, body=result.content)

# ...
response_content = content.decode("utf-8")  # content was never assigned

The synchronous path and arequest_raw both raise error.APIConnectionError for the same class of failure.

Repro

import asyncio, aiohttp
from together.abstract.api_requestor import APIRequestor
from together.types import TogetherClient

class FakeResp:
    status = 200
    headers = {"Content-Type": "application/json"}
    content = None
    async def read(self):
        raise aiohttp.ClientError("connection reset while reading body")
    def release(self): pass

async def main():
    req = APIRequestor(client=TogetherClient(api_key="fake"))
    await req._interpret_async_response(FakeResp(), stream=False)

asyncio.run(main())

Output (run twice, identical):

UnboundLocalError: local variable 'content' referenced before assignment

Expected: together.error.APIConnectionError.

Note: the 2.0 SDK (together-py) raises APIConnectionError correctly here; this only affects the V1 SDK.

Happy to send a PR with the fix and regression tests.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions