[Bug]: SSE client splits data lines on U+2028, U+2029 and U+0085, so streamed events fail to parse
メンテナーはふだん 2 日以内に返信
評価
この issue はまだ評価されていません。
説明
What happened?
parse_sse_stream in src/a2a/client/transports/http_helpers.py reads the stream with response.aiter_lines() (line 78). httpx's line decoder follows str.splitlines(), so it also ends a line at U+2028 (LINE SEPARATOR), U+2029 (PARAGRAPH SEPARATOR) and U+0085 (NEL). SSE line ends are only CR, LF and CRLF, and the docstring on line 73 says the parser conforms to the SSE spec.
The server writes these three characters raw: json_utils.dumps uses ensure_ascii=False (src/a2a/utils/json_utils.py:19). sse-starlette frames on CR/LF only, so it sends one data: line. The client splits that line into several. json.loads fails on the first piece, and the stream ends with A2AClientError('Invalid JSON-RPC response in SSE stream').
Any string field in a streamed event can hold these characters, for example message text, artifacts or status messages that quote a document. Resubscribing sends the same task snapshot, so that task stays unreadable over streaming. Non-streaming GetTask is not affected. The same parser is used by the JSON-RPC and REST transports and by the v0.3 compat transports.
This looks like a regression from #1132, which removed httpx-sse. httpx-sse 0.4.3 split SSE lines on CR/LF only (_splitlines_sse).
Repro (library level, using the versions pinned in uv.lock: sse-starlette 3.4.4, httpx 0.28.1)
import asyncio, json
import httpx
from sse_starlette.sse import ServerSentEvent
async def main():
data = json.dumps({"text": "before
after"}, ensure_ascii=False)
frame = ServerSentEvent(data=data).encode()
print(frame.count(b"data:")) # 1: the server sends one data line
async def body():
yield frame
resp = httpx.Response(200, content=body())
lines = [l async for l in resp.aiter_lines()]
print(len(lines)) # 3: the client sees the data line split in two
json.loads(lines[0][len("data: "):])
asyncio.run(main())
Expected: one data: line that parses as JSON. Observed: JSONDecodeError.
Possible fixes:
- Split SSE lines on CR, LF and CRLF only, with a small line decoder over
aiter_text(). - Also, or instead: escape U+2028, U+2029 and U+0085 in
json_utils.dumps.
Related: #1213, the end-of-stream flush in the same parser.
No existing tests cover these characters in SSE data.
Relevant log output
json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 10 (char 9)
Code of Conduct
- I agree to follow this project's Code of Conduct
Drafted with Claude Code. I reviewed the code paths and ran the repro.
- 主要言語
- Python
- スター
- 2.2k
- フォーク
- 532
- 平均マージ
- 3日 2時間
- マージ済み PR(30日)
- 46
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
a2aproject/a2a-python のほかの issue
-
[Bug]: `A2A-Version` validation ignores minor versions and the query parameter対応中かも @rohityan が 74 日前に担当しました。 オープンcomponent: server status:awaiting response status:stale
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
a2aproject/a2a-python#1204 · コメント 4 件 · 担当者 1 名 ·
メンテナーはふだん 2 日以内に返信
-
[Bug]: REST task/request id sanitization対応中かも @Linux2010 が 133 日前に担当しました。 オープンmaintainers-only
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
a2aproject/a2a-python#805 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
v0.3 REST and gRPC clients send blocking requests as non-blocking対応中かも @ConnorMoss02 が 1 日前に担当しました。 オープンcomponent: client
a2aproject/a2a-python#1428 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 2 日以内に返信
-
Compat REST client drops security from the v0.3 extended agent card対応中かも @ConnorMoss02 が 3 日前に担当しました。 オープンcomponent: client status:awaiting response
a2aproject/a2a-python#1418 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 2 日以内に返信
-
[Feat]: Add a task-state-invariants agent skill for sibling-surface propagation対応中かも @Linux2010 が 5 日前に担当しました。 オープンcomponent: tooling status:awaiting response
a2aproject/a2a-python#1413 · コメント 3 件 · 担当者 1 名 ·
メンテナーはふだん 2 日以内に返信
a2aproject/a2a-python の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
NVIDIA/auto-ontology#463 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
NousResearch/hermes-agent#151165 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信
-
code-health
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
tinaudio/synth-setter#3750 ·
メンテナーはふだん 1 日以内に返信
-
[Bug] vllm-sr config migrate drops providers.models[].deployment対応中かも @Bevisy が今日担当しました。 オープンneeds-acceptance wg/developer-experience-ecosystem
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
vllm-project/semantic-router#5996 ·
メンテナーはふだん 2 日以内に返信