Skip to content

fix: Bedrock stream silently drops exception/error frames#128

Open
Mingye-Lu wants to merge 2 commits into
mainfrom
fix/bedrock-error-frames
Open

fix: Bedrock stream silently drops exception/error frames#128
Mingye-Lu wants to merge 2 commits into
mainfrom
fix/bedrock-error-frames

Conversation

@Mingye-Lu

Copy link
Copy Markdown
Owner

Summary

  • parse_stream_event_payload tried to deserialize every Bedrock event-stream payload as StreamEvent and silently dropped it (.ok()) on failure. AWS's vnd.amazon.eventstream framing signals mid-stream errors (throttling, validation, internal errors) via :message-type/:exception-type headers, which parse_event_frame skipped over entirely without inspecting — so mid-stream Bedrock errors were discarded and the caller just saw the stream end early.
  • parse_event_frame now also parses and returns the header block (name/value pairs, covering all vnd.amazon.eventstream header value types). drain_frames checks each frame's headers via the new event_frame_error: if :message-type is "exception" or "error", it builds an ApiError::Api carrying the :exception-type/:error-code and a message extracted from the JSON payload (or :error-message header), with retryable set for the known-transient exception types (throttling/serviceUnavailable/internalServer/modelTimeout).

Test plan

  • test_parse_event_stream_headers_string_values — header block parsing
  • test_event_frame_error_none_for_normal_frame — non-error frames are untouched
  • test_event_frame_error_surfaces_exception_framethrottlingException frame surfaces as a retryable ApiError with correct type/message
  • test_event_frame_error_surfaces_validation_exception_as_non_retryablevalidationException surfaces as non-retryable
  • cargo test -p api (194 passed)
  • cargo fmt --check
  • cargo clippy -p api --all-targets -- -D warnings

parse_stream_event_payload tried to deserialize every event-stream
payload as StreamEvent and silently dropped it via .ok() on failure.
AWS's vnd.amazon.eventstream framing signals mid-stream errors
(throttling, validation, internal errors) via :message-type /
:exception-type headers, which parse_event_frame skipped over
entirely without inspecting -- so mid-stream Bedrock errors were
discarded and the caller just saw the stream end early.

parse_event_frame now also parses and returns the header block
(name/value pairs, supporting all vnd.amazon.eventstream header value
types). drain_frames checks each frame's headers via the new
event_frame_error: if :message-type is "exception" or "error", it
builds an ApiError::Api carrying the :exception-type/:error-code and
a message extracted from the JSON payload (or :error-message header),
with retryable set for the known-transient exception types
(throttling/serviceUnavailable/internalServer/modelTimeout).

Adds tests for: header parsing, a non-error frame producing no error,
a throttlingException frame surfacing as a retryable error with the
right type/message, and a validationException frame surfacing as
non-retryable.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@Mingye-Lu

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@Mingye-Lu

Copy link
Copy Markdown
Owner Author

@codex review — retrying, previous review attempt hit the Codex usage-limit error.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 436e3ed6f9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/api/src/bedrock.rs Outdated
);

Some(ApiError::Api {
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Map Bedrock stream exception statuses

When a Bedrock stream emits a non-500 exception such as validationException or throttlingException, this hard-coded status makes ApiError::Display report api returned 500 (...) even though the event-stream exception represents a 400/429 class failure. That gives users and any status-aware handling the wrong failure class; please map the Bedrock exception type to its documented status instead of always using INTERNAL_SERVER_ERROR.

Useful? React with 👍 / 👎.

Comment thread crates/api/src/bedrock.rs
Comment on lines +443 to +450
let retryable = matches!(
exception_type.as_deref(),
Some(
"throttlingException"
| "modelTimeoutException"
| "serviceUnavailableException"
| "internalServerException"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Treat stream error exceptions as retryable

When Bedrock emits modelStreamErrorException mid-stream, the service is telling us the stream failed after starting and the request should be retried, but this allow-list leaves it with retryable: false. In contexts that consult ApiError::is_retryable() this newly surfaced transient failure will be handled as terminal, unlike the other transient Bedrock stream errors listed here.

Useful? React with 👍 / 👎.

…xception as retryable

- Add bedrock_exception_status() to map Bedrock :exception-type headers
  to appropriate HTTP status codes (400/429/504/503/500)
- Replace hard-coded INTERNAL_SERVER_ERROR in event_frame_error()
  with the new mapping function
- Add modelStreamErrorException to the retryable exception set
- Add unit test for the full status mapping
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.

2 participants