Skip to content

adds EOF handler support to all providers - #5567

Merged
akshaydeo merged 1 commit into
devfrom
07-27-adds_eof_handler_support_to_all_providers
Jul 27, 2026
Merged

adds EOF handler support to all providers#5567
akshaydeo merged 1 commit into
devfrom
07-27-adds_eof_handler_support_to_all_providers

Conversation

@akshaydeo

@akshaydeo akshaydeo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Streaming providers that die mid-response close the connection with a plain io.EOF, which is indistinguishable from a healthy close at the transport layer. Previously, Bifrost would silently synthesize a terminal chunk and close the channel, presenting a truncated stream to the caller as if it had completed normally. This PR detects the missing terminal event (e.g., message_stop for Anthropic, [DONE] for OpenAI-compatible providers, done for Replicate) and surfaces a 502 truncation error on the stream instead, allowing retry logic to act on it.

Changes

  • Anthropic chat and responses streams: Track whether message_stop was received. If the loop falls through without it, emit a truncation error instead of the synthesized final chunk. Error paths now return rather than break to prevent the post-loop check from double-reporting.
  • Cohere chat and responses streams: Same return-instead-of-break fix on error paths, plus a post-loop truncation check since Cohere's terminal event is the only completion signal.
  • Azure speech stream: Replace the server-side-only warning with a SendStreamTruncatedError call so the caller can observe the truncation.
  • Mistral transcription stream: Post-loop truncation check guarded by the existing BifrostContextKeyStreamEndIndicator so already-reported read errors stay quiet.
  • OpenAI speech, transcription, image generation, and image edit streams: Post-loop truncation checks using both the stream-end indicator and SSEStreamEndedOnMarker to avoid false positives when [DONE] was received.
  • Replicate text completion, chat, responses, image generation, and image edit streams: Post-loop truncation checks guarded by the stream-end indicator, consistent with the done-event contract.
  • vLLM transcription stream: Post-loop truncation check using both the indicator and SSEStreamEndedOnMarker.
  • Tests: Three new tests for the Anthropic chat stream covering pre-first-byte death, mid-stream death, and a complete stream that must still receive its synthesized final chunk without error.

Type of change

  • Bug fix

Affected areas

  • Core (Go)
  • Providers/Integrations

How to test

go test ./core/providers/anthropic/... -run TestAnthropicChatStream
go test ./...

The three new Anthropic truncation tests spin up an in-process httptest.Server that either drops the connection mid-stream (panic(http.ErrAbortHandler)) or completes normally, and assert that:

  • A pre-first-byte drop produces exactly one chunk carrying a 502 truncation error.
  • A mid-stream drop forwards the partial content and appends a 502 truncation error as the final chunk.
  • A fully completed stream produces no error and includes the synthesized final chunk.

Breaking changes

  • Yes
  • No

Related issues

Closes #5546

Security considerations

None. The change only affects error reporting on the stream channel; no secrets or PII are involved.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 80f2e34c-7d96-4d2a-9519-50a053bac73f

📥 Commits

Reviewing files that changed from the base of the PR and between 195b962 and 359de69.

📒 Files selected for processing (9)
  • core/providers/anthropic/anthropic.go
  • core/providers/anthropic/streamtruncation_test.go
  • core/providers/azure/azure.go
  • core/providers/cohere/cohere.go
  • core/providers/mistral/mistral.go
  • core/providers/openai/openai.go
  • core/providers/openai/streamtruncation_test.go
  • core/providers/replicate/replicate.go
  • core/providers/vllm/vllm.go
🚧 Files skipped from review as they are similar to previous changes (9)
  • core/providers/vllm/vllm.go
  • core/providers/azure/azure.go
  • core/providers/cohere/cohere.go
  • core/providers/mistral/mistral.go
  • core/providers/openai/streamtruncation_test.go
  • core/providers/anthropic/anthropic.go
  • core/providers/replicate/replicate.go
  • core/providers/openai/openai.go
  • core/providers/anthropic/streamtruncation_test.go

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Streaming requests now clearly report when provider responses end unexpectedly, instead of silently completing.
    • Prevented duplicate error messages when a streaming connection fails.
    • Preserved usage and cached-token billing details on truncated Anthropic streams.
    • Azure speech streams now report missing completion markers as structured errors.
    • Improved handling of truncated text, chat, response, image, transcription, and audio streams across supported providers.
  • Tests

    • Added coverage for truncated streams, preserved content, billing details, successful completion, and duplicate-error prevention.

Walkthrough

Streaming handlers across seven providers now detect premature SSE termination, emit structured truncation errors, and avoid duplicate error or finalization handling. Anthropic adds terminal-event tracking, cached-usage normalization, and coverage for truncated and complete streams.

Changes

Provider stream termination

Layer / File(s) Summary
Anthropic terminal detection and validation
core/providers/anthropic/anthropic.go, core/providers/anthropic/streamtruncation_test.go
Anthropic streams distinguish message_stop from truncation, preserve cached-token billing, prevent duplicate handling, and test chat and responses flows.
Cohere stream exit handling
core/providers/cohere/cohere.go
Cohere streams return after terminal or conversion errors and report missing terminal events as truncation.
Cross-provider truncation guards
core/providers/azure/azure.go, core/providers/mistral/mistral.go, core/providers/openai/openai.go, core/providers/vllm/vllm.go
Handlers report missing completion markers or stream-end indicators, while OpenAI image handlers avoid duplicate read-error reporting.
Replicate stream termination checks
core/providers/replicate/replicate.go
Text, chat, response, image-generation, and image-edit streams report premature termination without terminal signaling.
OpenAI read-error validation
core/providers/openai/streamtruncation_test.go
Injected non-EOF SSE failures verify that image-generation and image-edit streams report the original read error exactly once.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant UpstreamSSE
  participant StreamingHandler
  participant SendStreamTruncatedError
  participant Client
  UpstreamSSE->>StreamingHandler: SSE events or premature body end
  StreamingHandler->>Client: Forward converted stream chunks
  StreamingHandler->>SendStreamTruncatedError: Report missing terminal event
  SendStreamTruncatedError->>Client: Send structured truncation error
Loading

Suggested reviewers: tejasghatte, danpiths, sammaji, roroghost17, pratham-mishra04

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: adding EOF/truncation handling across providers.
Description check ✅ Passed The PR description covers summary, changes, type, affected areas, testing, related issues, security, and checklist items.
Linked Issues check ✅ Passed The changes address #5546 by surfacing stream truncation instead of silently synthesizing successful completion.
Out of Scope Changes check ✅ Passed The diffs and tests stay focused on stream truncation handling and related provider coverage.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-27-adds_eof_handler_support_to_all_providers

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@akshaydeo
akshaydeo marked this pull request as ready for review July 27, 2026 03:12

akshaydeo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 7 seconds.

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 57 minutes.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
core/providers/replicate/replicate.go (1)

765-772: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add Replicate-specific truncation coverage.

The listed tests cover Anthropic, while these five guards change Replicate stream semantics. Add deterministic, table-driven tests for EOF before output, EOF mid-stream, and valid done events—covering text/chat plus at least one Responses/image path—and assert exactly one truncation error with no synthetic terminal chunk. Run provider tests with make test-core.

Based on the PR objective, the intended contract is distinguishable truncation without duplicate reporting. As per coding guidelines, behavior changes require deterministic/table-driven coverage and provider-level tests should use make test-core.

Also applies to: 1130-1136, 1711-1717, 2162-2168, 2556-2562

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/replicate/replicate.go` around lines 765 - 772, Add
deterministic, table-driven Replicate provider tests covering EOF before output,
EOF mid-stream, and valid done events across text/chat plus at least one
Responses or image path. Assert truncated streams emit exactly one truncation
error and no synthetic terminal chunk, while valid done events remain
successful. Cover each affected stream guard and run the provider suite with
make test-core.

Source: Coding guidelines

core/providers/anthropic/streamtruncation_test.go (1)

136-211: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding equivalent coverage for HandleAnthropicResponsesStream.

These tests only exercise ChatCompletionStream; the Responses-stream truncation path (anthropic.go lines ~1732-1737) has the same detection logic and the flagged usage-normalization gap, but no direct regression test. The existing helpers (anthropicSSEServer, collectTruncationChunks, assertAnthropicTruncationError) could be reused with a Responses-stream request/provider call.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/anthropic/streamtruncation_test.go` around lines 136 - 211,
Add equivalent truncation regression tests for HandleAnthropicResponsesStream,
covering pre-first-byte truncation, mid-stream truncation, and a complete
message_stop stream. Reuse anthropicSSEServer, collectTruncationChunks, and
assertAnthropicTruncationError, and invoke the Responses-stream request path
directly so detection and usage normalization are both exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/anthropic/anthropic.go`:
- Around line 1177-1192: Before each truncated-stream call to
providerUtils.SendStreamTruncatedError, invoke the applicable normalizeUsage()
or normalizeBilledUsage() for the chat and responses streaming paths. Update
both the sawTerminalEvent/fallthrough path and the deferred ctx.Err() path as
needed so cached read/write tokens are folded into billed usage before billing,
while preserving the existing idempotent normalization guards.

In `@core/providers/openai/openai.go`:
- Around line 3692-3693: The non-EOF ReadDataLine error paths must prevent the
later truncation guard from sending a duplicate stream error. Update the
preceding error handling for both core/providers/openai/openai.go:3692-3693 and
core/providers/openai/openai.go:5183-5184 to mark the stream ended or track that
an error was already sent, preserving single-error behavior in both the standard
and image-edit handlers.

---

Nitpick comments:
In `@core/providers/anthropic/streamtruncation_test.go`:
- Around line 136-211: Add equivalent truncation regression tests for
HandleAnthropicResponsesStream, covering pre-first-byte truncation, mid-stream
truncation, and a complete message_stop stream. Reuse anthropicSSEServer,
collectTruncationChunks, and assertAnthropicTruncationError, and invoke the
Responses-stream request path directly so detection and usage normalization are
both exercised.

In `@core/providers/replicate/replicate.go`:
- Around line 765-772: Add deterministic, table-driven Replicate provider tests
covering EOF before output, EOF mid-stream, and valid done events across
text/chat plus at least one Responses or image path. Assert truncated streams
emit exactly one truncation error and no synthetic terminal chunk, while valid
done events remain successful. Cover each affected stream guard and run the
provider suite with make test-core.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 664ec189-3e07-4c59-8485-f2be81937698

📥 Commits

Reviewing files that changed from the base of the PR and between 5fab498 and 52453d7.

📒 Files selected for processing (8)
  • core/providers/anthropic/anthropic.go
  • core/providers/anthropic/streamtruncation_test.go
  • core/providers/azure/azure.go
  • core/providers/cohere/cohere.go
  • core/providers/mistral/mistral.go
  • core/providers/openai/openai.go
  • core/providers/replicate/replicate.go
  • core/providers/vllm/vllm.go

Comment thread core/providers/anthropic/anthropic.go
Comment thread core/providers/openai/openai.go
@akshaydeo
akshaydeo force-pushed the 07-27-adds_eof_handler_support_to_all_providers branch from 52453d7 to d0c6d7d Compare July 27, 2026 06:52
@akshaydeo
akshaydeo force-pushed the 07-27-adds_ssetruncation_interface_for_handling_eof_cases branch from 5fab498 to ac5af2e Compare July 27, 2026 06:52

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/anthropic/streamtruncation_test.go`:
- Around line 172-183: Strengthen the truncation tests around
collectTruncationChunks: in the mid-stream case, require at least one pre-error
chunk containing the expected “partial answer” content before asserting the
terminal Anthropic truncation error; in the complete case, assert the final
chunk is the synthesized terminal-only chunk by requiring its expected usage or
finish metadata, rather than merely checking for a non-nil response.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f6307a20-6095-48d7-95a5-40a57d500209

📥 Commits

Reviewing files that changed from the base of the PR and between 52453d7 and d0c6d7d.

📒 Files selected for processing (9)
  • core/providers/anthropic/anthropic.go
  • core/providers/anthropic/streamtruncation_test.go
  • core/providers/azure/azure.go
  • core/providers/cohere/cohere.go
  • core/providers/mistral/mistral.go
  • core/providers/openai/openai.go
  • core/providers/openai/streamtruncation_test.go
  • core/providers/replicate/replicate.go
  • core/providers/vllm/vllm.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • core/providers/mistral/mistral.go
  • core/providers/azure/azure.go
  • core/providers/vllm/vllm.go
  • core/providers/cohere/cohere.go
  • core/providers/replicate/replicate.go
  • core/providers/anthropic/anthropic.go
  • core/providers/openai/openai.go

Comment thread core/providers/anthropic/streamtruncation_test.go
@akshaydeo
akshaydeo force-pushed the 07-27-adds_eof_handler_support_to_all_providers branch from d0c6d7d to 195b962 Compare July 27, 2026 07:17
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026

akshaydeo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jul 27, 9:25 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 27, 9:27 AM UTC: Graphite rebased this pull request as part of a merge.
  • Jul 27, 9:28 AM UTC: Graphite couldn't merge this PR because it was not satisfying all requirements (PR does not have required approvals).
  • Jul 27, 9:46 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 27, 9:46 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 07-27-adds_ssetruncation_interface_for_handling_eof_cases to graphite-base/5567 July 27, 2026 09:25
@akshaydeo
akshaydeo changed the base branch from graphite-base/5567 to dev July 27, 2026 09:26
@akshaydeo
akshaydeo dismissed stale reviews from Pratham-Mishra04 and coderabbitai[bot] July 27, 2026 09:26

The base branch was changed.

@akshaydeo
akshaydeo force-pushed the 07-27-adds_eof_handler_support_to_all_providers branch from 195b962 to 359de69 Compare July 27, 2026 09:26
@coderabbitai
coderabbitai Bot requested a review from Pratham-Mishra04 July 27, 2026 09:28
@akshaydeo
akshaydeo merged commit a89d3b8 into dev Jul 27, 2026
13 checks passed
@akshaydeo
akshaydeo deleted the 07-27-adds_eof_handler_support_to_all_providers branch July 27, 2026 09:46
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.

[Bug]: Upstream SSE stream death swallowed into a clean [DONE] — dead streams appear successful (v1.5.16 through v1.6.5)

3 participants