Skip to content

Fix missing signed empty end frame on event stream close#691

Merged
jonathan343 merged 6 commits intosmithy-lang:developfrom
alexgromero:fix-event-stream-missing-end-frame
May 5, 2026
Merged

Fix missing signed empty end frame on event stream close#691
jonathan343 merged 6 commits intosmithy-lang:developfrom
alexgromero:fix-event-stream-missing-end-frame

Conversation

@alexgromero
Copy link
Copy Markdown
Contributor

@alexgromero alexgromero commented May 4, 2026

Issue #, if available:
awslabs/aws-sdk-python#46

Description of changes:
Fix AWSEventPublisher.close() to send a signed empty end frame to signal stream completion.

SigV4 signed event streams require a final signed empty message before the HTTP body stream closes. This fix:

  1. Adds sign_empty() method to the EventSigner protocol in smithy-core.
  2. Updates AWSEventPublisher.close() to call sign_empty() when sending the termination frame in smithy-aws-event-stream.

This eliminates the following errors:

  • Transcribe Streaming: BadRequestException: A complete signal was sent without the preceding empty frame.
  • Bedrock Runtime: ValidationException: Invalid input request, please fix your input and try again.

Related PR: #692

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@alexgromero alexgromero requested a review from a team as a code owner May 4, 2026 14:34
@Alan4506
Copy link
Copy Markdown
Contributor

Alan4506 commented May 4, 2026

Just curious: with this change applied, are we able to modify some existing integration tests to remove await asyncio.sleep statements? For example, Bedrock Runtime and Transcribe Streaming? When I wrote tests for new clients (e.g., Lex Runtime V2 and Q business), I also had similar concerns - tests would fail without await asyncio.sleep statements.

Alan4506
Alan4506 previously approved these changes May 4, 2026
@Alan4506
Copy link
Copy Markdown
Contributor

Alan4506 commented May 4, 2026

Approved. However, there are some other issues when I test this with the Transcribe Streaming integration tests and the simple_file.py example. The end frame fix resolves the "complete signal was sent without the preceding empty frame" error, but the asyncio.sleep calls before close() seem still needed. Without them, it returns aws_sdk_transcribe_streaming.models.BadRequestException: Could not decode the audio stream that you provided. Check that the audio stream is valid and try your request again. I wonder if this is expected behavior or something that needs a separate fix.

@alexgromero alexgromero force-pushed the fix-event-stream-missing-end-frame branch from 134559e to 8a357d1 Compare May 4, 2026 21:35
@alexgromero alexgromero changed the title Send signed empty end frame on event stream close Fix missing signed empty end frame on event stream close May 4, 2026
Alan4506
Alan4506 previously approved these changes May 5, 2026
return
self._closed = True

# Send a signed empty frame to signal stream completion.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we wrap the signed-empty-frame write in a try/finally so the writer is always closed?

It may also be worth making the test assert that the writer is closed, or using AsyncBytesProvider to decode the written frame and verify the terminator payload is actually empty.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in d1fc057.

return
self._closed = True

# Send a signed empty frame to signal stream completion.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if this is safe for even non-bidirectional APIs?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized all AWS operations that use input streaming are also bi-directional

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, thanks for confirming! Also worth noting the Java SDK sends the trailing empty frame unconditionally for all signed event streams, no bidi check, so this appears to be part of the SigV4 protocol itself rather than a bidi-specific behavior.

@jonathan343 jonathan343 merged commit abc1a00 into smithy-lang:develop May 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants