Skip to content

SSE streaming from Gemini fails — chunked transfer encoding chunk size parsed as HTTP response header #1613

@KuljeetSinghXDA

Description

@KuljeetSinghXDA

Prerequisites

  • I have searched existing issues and discussions to avoid duplicates
  • I am using the latest version (or have tested against main/nightly)

Description

Bug Report

Environment

  • Bifrost version: maximhq/bifrost:latest (Docker)
  • Upstream provider: Google Gemini (gemini-3-flash-preview)
  • Endpoint: /pydanticai/v1 (OpenAI-compatible, streaming SSE)
  • Client: Pydantic AI OpenAIProvider → Bifrost → Gemini

Error

error when reading response headers: cannot find whitespace in the first line
of response "217\r\ndata: {"candidates": [{"content": ...}]}\r\n\r\n\r\n".
Buffer size=542

What's happening

During streaming SSE responses from Gemini, Bifrost's HTTP proxy layer
misinterprets a chunked transfer encoding chunk size header (217\r\n)
as the first line of a new HTTP response.

217 is the hex chunk size (535 bytes), followed by the SSE data: payload.
The proxy appears to be parsing this as an HTTP status line and failing
because there's no space (e.g., HTTP/1.1 200 OK).

The actual Gemini response content is valid — the model returned a complete
data: SSE event with candidates, usage metadata, and model version.

Expected behavior

Bifrost should correctly handle HTTP/1.1 chunked transfer encoding when
proxying streaming SSE responses from Gemini, passing through the decoded
chunks as SSE events to the client.

Reproduction

  1. Configure Bifrost with a Gemini provider (gemini-3-flash-preview)
  2. Send a streaming request via the /pydanticai/v1 endpoint
  3. Intermittent failure during mid-stream chunk boundaries

Impact

Intermittent — fails when a chunk boundary happens to be parsed at
the wrong layer. Causes dropped LLM responses in production.

Steps to reproduce

error when reading response headers: cannot find whitespace in the first line of response "217\r\ndata: {"candidates": [{"content": {"role": "model","parts": [{"text": " said \"i want to loose weight\" which is a goal, not necessarily a symptom. But the system says \"Already Collected... ['Weight Gain']\". I will treat \"Weight Gain\" as the underlying symptom they are addressing.\n\nReady.\n\nText:\nWeight is a mirror of deeper rhythms—\nhow we"}]}}],"usageMetadata": {"trafficType": "ON_DEMAND"},"modelVersion": "gemini-3-flash-preview","createTime": "2026-02-11T14:30:56.608799Z","responseId": "oJKMaZ-UJf2OseMPjKrliQc"}\r\n\r\n\r\n". Buffer size=542, contents: "217\r\ndata: {"candidates": [{"content": {"role": "model","parts": [{"text": " said \"i want to loose weight\" which is a goal, not necessarily a symptom. But the system says \"Already Collected... ['We"..."ythms—\nhow we"}]}}],"usageMetadata": {"trafficType": "ON_DEMAND"},"modelVersion": "gemini-3-flash-preview","createTime": "2026-02-11T14:30:56.608799Z","responseId": "oJKMaZ-UJf2OseMPjKrliQc"}\r\n\r\n\r\n"

Expected behavior

error free

Actual behavior

error

Affected area(s)

Transports (HTTP)

Version

1.4.5

Environment


Relevant logs/output

Regression?

No response

Severity

High (major functionality broken)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions