openclaw - ✅(Solved) Fix [Bug]: Gateway SSE streaming corrupts response when stripping <final> tags [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#63325Fetched 2026-04-09 07:55:18
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
labeled ×2

When using /v1/chat/completions with stream: true, the gateway's <final> tag stripping corrupts the response — it removes actual content lines along with the tags.

Root Cause

When using /v1/chat/completions with stream: true, the gateway's <final> tag stripping corrupts the response — it removes actual content lines along with the tags.

Fix Action

Fix / Workaround

Affected: All streaming API consumers when agent uses tools. Severity: High (silent data loss). Frequency: 100%. Workaround: stream: false.

PR fix notes

PR #63635: fix: preserve content when stripping final tags in SSE streaming

Description (problem / solution / changelog)

Summary

Fixes SSE streaming response corruption caused by the /v1/chat/completions handler silently dropping content when <final>/<think> tags straddle chunk boundaries.

Root cause: The upstream subscribe handler strips reasoning tags from streamed text. When a tag is split across chunks, it first emits a delta with a partial tag remnant and then, once the full tag is recognised in the accumulated buffer, emits a replace event (replace: true, delta: "") whose text field carries the corrected full content. The SSE handler only looked at delta, so replace events with an empty delta were silently discarded, causing entire response lines to vanish.

Fix: Track the accumulated text already sent to the SSE client and always derive the incremental content from the authoritative text field (the full cleaned buffer) rather than the per-chunk delta. This prevents both partial tag remnants from leaking and content from being silently dropped on replace events.

Closes #63325

Changes

  • Modified src/gateway/openai-http.ts: Added accumulatedSent tracking and text-based delta derivation in the SSE streaming event handler
  • Added regression test in src/gateway/openai-http.test.ts covering the replace-event scenario

Testing

  • Added e2e test simulating partial <final> tag split across chunks with a replace event
  • All existing tests pass (TypeScript type-check, oxlint, and pre-commit hooks all pass)
  • Verified backward compatibility: events with only delta (no text) still work via fallback path

This PR was generated with AI assistance (Claude).

Changed files

  • src/gateway/openai-http.test.ts (modified, +61/-0)
  • src/gateway/openai-http.ts (modified, +47/-1)
  • ui/src/ui/chat-model-ref.ts (modified, +1/-1)

PR #63894: fix: preserve content when stripping final tags in SSE streaming

Description (problem / solution / changelog)

Summary

The /v1/chat/completions SSE streaming path dropped response content when <final>/<think> tags straddled chunk boundaries. The upstream handler detects cross-boundary tags and emits replace events with corrected full text, but the SSE handler only looked at delta, silently discarding replace events with empty deltas.

Closes #63325

Changes

  • Track accumulated sent text via accumulatedSent in the SSE streaming handler
  • Derive incremental SSE deltas from the authoritative text field instead of raw delta
  • Use common-prefix matching on replace events to avoid duplicating already-sent content
  • Added test covering replace events during final-tag stripping

Testing

  • New test: preserves content when upstream emits replace events during final-tag stripping
  • Verifies no content loss and no duplication on replace events

This PR was developed with AI assistance (Claude). Built with islo.dev

Changed files

  • src/gateway/openai-http.test.ts (modified, +53/-0)
  • src/gateway/openai-http.ts (modified, +24/-1)

Code Example

Debug output: delta 1: '<', delta 2: ' household items...Summary: A person...', delta 3: '...No</'. Session log shows full response was present internally.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When using /v1/chat/completions with stream: true, the gateway's <final> tag stripping corrupts the response — it removes actual content lines along with the tags.

Steps to reproduce

  1. Send a streaming request that triggers tool use: curl -s -N -X POST localhost:18789/v1/chat/completions with stream:true
  2. Agent internally produces a multi-line response wrapped in <final> tags
  3. SSE chunks are missing entire lines of the response

Expected behavior

Gateway strips <final> tags cleanly; all response lines present. Non-streaming (stream: false) works correctly.

Actual behavior

SSE sends 3 chunks for a 6-line response. Chunk 1: < (remnant). Chunk 2: starts mid-subtitle, Title line is gone. Chunk 3: ends with </ (remnant).

OpenClaw version

2026.4.5

Operating system

Linux (Ubuntu, Docker)

Install method

docker (ghcr.io/openclaw/openclaw:latest)

Model

google/gemma-4-31b-it

Provider / routing chain

openclaw -> google-generative-ai

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Debug output: delta 1: '<', delta 2: ' household items...Summary: A person...', delta 3: '...No</'. Session log shows full response was present internally.

Impact and severity

Affected: All streaming API consumers when agent uses tools. Severity: High (silent data loss). Frequency: 100%. Workaround: stream: false.

Additional information

No response

extent analysis

TL;DR

The gateway's <final> tag stripping mechanism is likely causing the corruption of the response when using the /v1/chat/completions endpoint with stream: true, resulting in missing content lines.

Guidance

  • Verify that the issue is indeed caused by the <final> tag stripping by checking the gateway's configuration and logs to see if there are any errors or warnings related to tag stripping.
  • Investigate the gateway's implementation of the <final> tag stripping mechanism to see if it's correctly handling multi-line responses wrapped in <final> tags.
  • Consider modifying the agent to not wrap the response in <final> tags when stream: true to avoid the stripping issue.
  • Test the workaround of setting stream: false to see if it resolves the issue, although this may not be a viable long-term solution.

Example

No code snippet is provided as the issue is related to the gateway's configuration and implementation.

Notes

The issue seems to be specific to the OpenClaw version 2026.4.5 and the google/gemma-4-31b-it model, but it's unclear if this is a version-specific bug or a more general issue with the gateway's <final> tag stripping mechanism.

Recommendation

Apply workaround: set stream: false until a more permanent fix can be implemented, as this has been confirmed to resolve the issue, although it may not be desirable for all use cases.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Gateway strips <final> tags cleanly; all response lines present. Non-streaming (stream: false) works correctly.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING