Skip to content

AIO HTTP/2 writer task raises unhandled AWS_ERROR_HTTP_STREAM_HAS_COMPLETED during normal shutdown #762

Description

@pgrayy

Describe the bug

Closing an HTTP/2 bidirectional request through the client's async context managers can leave AIOHttp2ClientStream._set_request_body_generator() with an unobserved exception. Its final end-stream write raises AWS_ERROR_HTTP_STREAM_HAS_COMPLETED, producing:

Task exception was never retrieved

Regression Issue

Unchecked — I have not established an earlier working version.

Expected Behavior

Normal stream/client shutdown should not produce an unhandled asyncio task exception. The request-writer task should be observed, and stream completion during its final end-stream write should be handled as part of shutdown.

Current Behavior

Task exception was never retrieved
future: <Task ... coro=<AIOHttp2ClientStream._set_request_body_generator() ...>
Traceback (most recent call last):
  File "awscrt/aio/http.py", line 532, in _set_request_body_generator
    await self._write_data(None, True)
  File "awscrt/aio/http.py", line 524, in _write_data
    _awscrt.http2_client_stream_write_data(...)
RuntimeError: 2080 (AWS_ERROR_HTTP_STREAM_HAS_COMPLETED):
HTTP-stream has completed, action cannot be performed.

Reproduction Steps

Requires AWS credentials and access to Amazon Nova Sonic.

import asyncio
import gc
import json
import os
import uuid

from aws_sdk_bedrock_runtime.client import AsyncBedrockRuntimeClient
from aws_sdk_bedrock_runtime.config import AsyncBedrockRuntimeConfig
from aws_sdk_bedrock_runtime.models import (
    BidirectionalInputPayloadPart,
    InvokeModelWithBidirectionalStreamInputChunk,
    InvokeModelWithBidirectionalStreamOperationInput,
)
from smithy_http.aio.crt import AWSCRTHTTPClient


async def send(stream, event):
    payload = json.dumps({"event": event}).encode()
    await stream.input_stream.send(
        InvokeModelWithBidirectionalStreamInputChunk(
            value=BidirectionalInputPayloadPart(bytes_=payload)
        )
    )


async def main():
    config = await AsyncBedrockRuntimeConfig.resolve(
        region=os.getenv("AWS_REGION", "us-east-1"),
        transport=AWSCRTHTTPClient(),
    )
    async with AsyncBedrockRuntimeClient(config=config) as client:
        stream = await client.invoke_model_with_bidirectional_stream(
            InvokeModelWithBidirectionalStreamOperationInput(
                model_id="amazon.nova-2-sonic-v1:0"
            )
        )
        async with stream:
            prompt = str(uuid.uuid4())
            await send(stream, {"sessionStart": {"inferenceConfiguration": {}}})
            await send(
                stream,
                {
                    "promptStart": {
                        "promptName": prompt,
                        "textOutputConfiguration": {"mediaType": "text/plain"},
                        "audioOutputConfiguration": {
                            "mediaType": "audio/lpcm",
                            "sampleRateHertz": 16000,
                            "sampleSizeBits": 16,
                            "channelCount": 1,
                            "voiceId": "matthew",
                            "encoding": "base64",
                            "audioType": "SPEECH",
                        },
                    }
                },
            )
            await send(stream, {"promptEnd": {"promptName": prompt}})
            await send(stream, {"connectionEnd": {}})

    gc.collect()  # Make reporting of the unobserved task deterministic.
    await asyncio.sleep(0.1)


asyncio.run(main())

Possible Solution

AIOHttpClientStreamUnified creates the request-writer task with create_task() but does not subsequently observe it. The stream should retain and retrieve/await that task during shutdown, handling code 2080 when the stream has already completed.

Additional Information/Context

  • Reproduces without an application framework, using the generated client's supported async context managers.
  • aws-sdk-bedrock-runtime==0.11.0
  • smithy-http==0.5.0
  • Related to, but distinct from, aws/aws-sdk-python#13, which reports an InvalidStateError on output-stream close.

aws-crt-python version used

0.32.2

Python version used

3.12.13

Operating System and version

macOS 26.6.2

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