Skip to content

Fix JSON-RPC notification responses - #267

Open
GhostStar wants to merge 2 commits into
drpcorg:mainfrom
GhostStar:fix/json-rpc-notifications
Open

Fix JSON-RPC notification responses#267
GhostStar wants to merge 2 commits into
drpcorg:mainfrom
GhostStar:fix/json-rpc-notifications

Conversation

@GhostStar

Copy link
Copy Markdown
Contributor

Summary

  • suppress responses for JSON-RPC requests whose id member is absent
  • keep explicit id: null distinct and return a valid response for it
  • keep executing notifications while returning no WebSocket frame or HTTP 204
  • filter notifications from mixed batches and preserve response ordering
  • allow the HTTP writer to emit an empty 204 response safely

Root cause

viem sends this notification every 30 seconds as its WebSocket keepalive:

{"jsonrpc":"2.0","method":"net_version","params":[]}

NodeCore mapped the missing client ID to an empty byte slice and serialized a response as:

{"id":,"jsonrpc":"2.0","result":"4663"}

That invalid frame makes viem fail JSON parsing and close the shared subscription socket. JSON-RPC 2.0 notifications must not receive a response.

Tests

  • handler tests for missing IDs, explicit null IDs, and mixed batch ordering
  • HTTP integration test verifies 204 with an empty body
  • WebSocket integration test verifies silence followed by a successful regular response on the same connection
  • go test ./internal/server/http_server -count=1
  • make build

The full suite passes except for the pre-existing timing-sensitive TestEngineSlowConsumerDoesNotAffectFastPeer when run under full-suite load; it passes independently for 3 consecutive runs.

@mxssl
mxssl requested a review from KirillPamPam July 12, 2026 11:09
@KirillPamPam

Copy link
Copy Markdown
Collaborator

@GhostStar Hello! Thanks a lot for your support and flagging this bug!
We have reviewed the same behaviour among several providers and how they respond with omitted id. They just add "id": null in each response. So I think that the simplest solution for nodecore is to do it in the same way - https://github.com/drpcorg/nodecore/blob/main/internal/protocol/response.go#L374 just check if a realId is null and then set a default []byte("null") value.
What do you think?

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.

2 participants