a2aproject / a2aproject/a2a-java
[Bug]: SSE client rejects any event whose data arrives on a single line over 64KB, with no way to configure the limit
- Ngôn ngữ chính
- Java
- Star
- 490
- Fork
- 172
- Merge trung bình
- 1 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 55
Mô tả
### What happened?
`ServerSentEventParser` enforces a hard-coded 64 KB limit on a single SSE line. Any A2A server that
serializes an event as one `data:` field larger than that is unreadable by the Java client, and there
is no way for an application to raise, lower or disable the limit.
We hit this against a production agent whose final `TaskArtifactUpdateEvent` carries a large result
artifact. The stream opens, runs, and then dies mid-flight:
java.lang.IllegalArgumentException: Line exceeds maximum length of 65536 characters
at org.a2aproject.sdk.client.http.ServerSentEventParser.processLine(ServerSentEventParser.java:58)
**Why we think this is a bug rather than intended hardening**
1. Neither the [SSE specification]
nor the A2A specification places any limit on line length, so a server emitting a 200 KB `data:`
line is fully conformant. The Java client is the only participant that rejects it.
2. The limit is inconsistent with the parser's own per-event budget. `MAX_BUFFER_CHARS` allows 1 MB
of data spread across up to `MAX_BUFFER_SIZE` = 1000 lines. So the *same* 200 KB payload is
accepted when the server splits it across several `data:` lines and rejected when it sends one.
The DoS exposure is identical either way — the parser buffers the same total — so the per-line cap
costs interoperability without buying protection the per-event caps do not already provide.
3. It is not interoperable with the other A2A SDKs. The Python SDK reads streams with `httpx-sse`,
which accumulates `data:` lines until a blank line and imposes no per-line ceiling. A server that
every Python client reads happily is unreadable from Java. In our case the producer is
`a2a-sdk==1.1.0` (Python) serving through `sse-starlette`, which emits `json.dumps(...)` as a
single `data:` field because compact JSON contains no newlines — so this is the default framing of
the reference Python server, not an unusual choice.
**What we expected**
Either of:
- the per-line limit to be configurable (constructor parameter, builder option, or system property),
alongside the existing buffer limits; or
- the per-line limit to be removed, leaving `MAX_BUFFER_CHARS` / `MAX_BUFFER_SIZE` as the DoS bound,
since they already cap total memory per event.
Making all three configurable together would be ideal — 1 MB per event is also reachable for agents
returning large artifacts.
**Minimal reproducer**
String hugeJson = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"" + "x".repeat(70_000) + "\"}";
List events = new ArrayList<>();
List errors = new ArrayList<>();
ServerSentEventParser parser = new ServerSentEventParser(events::add, errors::add);
parser.processLine("data: " + hugeJson);
parser.processLine("");
// events is empty; errors holds IllegalArgumentException("Line exceeds maximum length of 65536 characters")
// Splitting the same payload across two `data:` lines parses fine.
**Environment**
- `a2a-java-sdk-client` / `a2a-java-sdk-http-client` `1.1.0.Final`, JDK transport
(`JdkA2AHttpClient`), JSON-RPC transport binding
- Also present unchanged in `v1.3.0.Final` and on `main` at time of writing
- Server: Python `a2a-sdk` 1.1.0 behind `sse-starlette` 3.4.6
**Source**
`http-client/src/main/java/org/a2aproject/sdk/client/http/ServerSentEventParser.java`
private static final int MAX_BUFFER_SIZE = 1000;
private static final int MAX_BUFFER_CHARS = 1024 * 1024; // 1 MB
private static final int MAX_LINE_LENGTH = 65536; // 64 KB
public void processLine(@Nullable String line) {
...
if (line.length() > MAX_LINE_LENGTH) {
handleError(new IllegalArgumentException("Line exceeds maximum length of " + MAX_LINE_LENGTH + " characters"));
skippingCurrentEvent = true;
Because `ServerSentEventParser` is shared across the HTTP client implementations, this affects every
transport that streams over SSE, not just the JDK one.
### Relevant log output
```shell
2026-09-01 11:30:35 WARN Downstream A2A call failed: method=SendStreamingMessage, rpcId=g-bdf28358-f7e1-41c1-91e1-417005473594,
url=http://localhost...:8000,
message=Line exceeds maximum length of 65536 characters
java.lang.IllegalArgumentException: Line exceeds maximum length of 65536 characters
at org.a2aproject.sdk.client.http.ServerSentEventParser.processLine(ServerSentEventParser.java:58)
```
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.