Skip to content

fix(jsonrpc): avoid NumberFormatException on every SSE event for string request IDs - #1254

Merged
kabir merged 1 commit into
a2aproject:mainfrom
sumitvairagar:issue-1253
Nov 2, 2026
Merged

kabir merged 1 commit into
a2aproject:mainfrom
sumitvairagar:issue-1253

Conversation

@sumitvairagar

@sumitvairagar sumitvairagar commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What

JSONRPCUtils.getAndValidateId() called getAsInt() on every JSON-RPC response ID, which threw NumberFormatException for string IDs (the UUID-based client default) before falling back to getAsString(). For a streaming session this exception was thrown and caught on every single SSE event, allocating a full stack trace each time.

Why it matters

The client generates a UUID string as the request ID by default (UUID.randomUUID().toString() in toJsonRPCRequest). The server echoes that ID on each streamed response. For every event in a streaming session, parseResponseEvent → getAndValidateId threw NumberFormatException before reading the ID correctly. The result was correct, but the cost was one stack-trace allocation per event.

Fix

Check the JSON primitive type before attempting integer parsing:

JsonPrimitive primitive = jsonRpc.getAsJsonPrimitive("id");
id = primitive.isNumber() ? primitive.getAsInt() : primitive.getAsString();
  • JSON number literals (e.g. 123) → Integer via getAsInt(), no exception.
  • Any string primitive (UUID, "123", "2147483648", or any other string) → returned as String without parsing. No exception, no overflow risk.

Tests

Updated existing tests that asserted numeric string IDs (e.g. "1", "2", "5") returned Integer — those now correctly expect String.

Four regression tests added to JSONRPCUtilsTest:

  • testGetAndValidateId_UuidStringId_ReturnsString — UUID string returns String, no exception
  • testGetAndValidateId_NumericStringId_ReturnsString — "123" returns String (not parsed as Integer)
  • testGetAndValidateId_NumericStringIdOutsideIntRange_ReturnsString — "2147483648" returns String safely (no overflow)
  • testGetAndValidateId_NumericId_ReturnsInteger — JSON number literal 42 returns Integer

54 tests pass.

Fixes #1253.

@kabir

kabir commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

I think this needs two changes before merging:

  1. Valid string IDs outside the integer range now fail parsing. In getAndValidateId(), INTEGER_STRING_PATTERN matches IDs such as "2147483648" and "1700000000000", but the subsequent Integer.parseInt(raw) throws an uncaught NumberFormatException. Previously these were returned as strings by the fallback. I reproduced the regression through both parseRequestBody() and parseResponseEvent() using the PR source.

  2. Numeric strings should remain strings, as agreed in [Bug]: JSONRPCUtils.getAndValidateId throws and catches NumberFormatException for every SSE event when id is a string (client default) #1253. My issue comment asked for numeric string IDs such as "123" to be preserved as strings, with the existing tests updated accordingly. The PR instead retains the integer conversion and adds a test requiring it. That conversion also loses the original representation of IDs such as "00123".

Please use the primitive type check proposed in the issue:

JsonPrimitive primitive = jsonRpc.getAsJsonPrimitive("id");
id = primitive.isNumber() ? primitive.getAsInt() : primitive.getAsString();

This removes the exception cost for UUID IDs and preserves all string IDs without parsing them as integers. Please update the numeric-string test to expect a String, adjust any existing expectations, and add coverage for a numeric string outside the integer range.

The PR's 52 tests passed when compiled and run against local dependencies; the additional probes exposed the regression above.

@kabir

kabir commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Also you need to rebase on the current state of the main branch

…ng request IDs

JSONRPCUtils.getAndValidateId() called getAsInt() on every JSON-RPC response ID,
which threw NumberFormatException for string IDs (the UUID-based client default)
before falling back to getAsString(). For a streaming session this exception was
thrown and caught on every single SSE event, allocating a full stack trace each time.

Fix: check the JSON primitive type before attempting integer parsing. JSON number
literals are read with getAsInt() directly. String primitives — UUIDs, numeric
strings, any string — are returned as String without parsing or exception.

Updated existing tests that asserted numeric string IDs (e.g. "1", "2", "5")
returned Integer — those now correctly expect String. Added four regression tests
covering UUID string ID, numeric string ID, out-of-range numeric string, and JSON
number literal.

This fixes a2aproject#1253.
@sumitvairagar

Copy link
Copy Markdown
Contributor Author

Thanks @kabir — both issues addressed in the updated commit:

  1. Simplified to your suggested one-liner: primitive.isNumber() ? primitive.getAsInt() : primitive.getAsString() — no pattern matching, no parseInt, no overflow risk.
  2. Updated existing tests that were asserting numeric string IDs (e.g. "1", "2", "5") returned Integer — those now correctly expect String. Added four regression tests covering UUID string, numeric string, out-of-range numeric string ("2147483648"), and JSON number literal.

Also rebased onto current main.

@kabir

kabir commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

The code changes look good now, thanks. Could you also update the PR description? It still describes the regex approach and says numeric string IDs are converted to integers.

Please describe the primitive type check, clarify that all string IDs remain strings, and update the test summary to include the out-of-range numeric string case and the 54 passing tests.

@sumitvairagar

Copy link
Copy Markdown
Contributor Author

Done @kabir — PR description updated to reflect the primitive type check, clarify that all string IDs remain strings, and include the out-of-range numeric string test case and the 54 passing tests.

@kabir
kabir merged commit e8f23b9 into a2aproject:main Nov 2, 2026
15 checks passed
@kabir

kabir commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks @sumitvairagar !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: JSONRPCUtils.getAndValidateId throws and catches NumberFormatException for every SSE event when id is a string (client default)

2 participants