Skip to content

[bug] SSE decoder drops data: fields without a space after the colon #399

Description

@ting-hong-shieh

Symptom

The shared SSE decoder silently drops valid data: fields when the colon is not followed by a space. An upstream stream that emits data:{...} instead of data: {...} therefore produces no normalized response chunks.

The WHATWG event-stream parser treats one space after the colon as optional: it collects the value after the colon and removes a single leading space only when one is present.

Reproduction

Add this focused regression test next to decode_stream_parses_sse_bytes_into_ir_chunks in crates/switchyard-translation/src/helpers.rs:

#[test]
fn decode_stream_accepts_sse_data_without_optional_space() -> Result<(), LlmClientError> {
    let sse = b"data:{\"choices\":[{\"delta\":{\"content\":\"Hello\"}}]}\n\n\
         data:[DONE]\n\n"
        .to_vec();
    let bytes = stream::once(async move { Ok::<Vec<u8>, LlmClientError>(sse) });
    let chunks = decode_all(bytes, WireFormat::OpenAiChat)?;
    assert_eq!(text_of(&chunks), "Hello");
    Ok(())
}

Run:

cargo test -p switchyard-translation decode_stream_accepts_sse_data_without_optional_space -- --nocapture

The assertion fails with:

assertion `left == right` failed
  left: ""
 right: "Hello"

parse_json_sse_frame currently filters with line.strip_prefix("data: "), so both the payload and the no-space data:[DONE] marker are ignored.

Expected vs. actual

  • Expected: data:{...} and data: {...} decode to the same event payload. A no-space data:[DONE] terminates the stream.
  • Actual: no-space data fields are treated as empty frames and silently discarded.

Environment

  • Switchyard commit SHA: b256d936f1d77bf13ec9bec399ea0a253e07ca05
  • Rust version: rustc 1.96.1 (31fca3adb 2026-06-26)
  • OS / arch: macOS 26.5.2, arm64
  • Install path: source checkout
  • Inbound format: OpenAI Chat Completions, streaming
  • Backend: local byte-stream fixture; no provider credentials

Additional context

The existing decoder test covers only data: {...}. A fix could parse the field name at the first colon, accept both spellings, and remove at most one optional leading space from the value.

I searched open and closed issues and pull requests for data: without space, optional space SSE, parse_json_sse_frame, and SSE parser drops data; I found no matching report or in-flight fix.

I'm happy to send a PR with the parser change and regression coverage if this direction looks right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions