[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 小時
- 30 天內合併 PR
- 46
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 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 天內回覆