skip to content

What makes a JSON-RPC 2.0 message a notification, and why can the client never learn that one failed?

level: middleimportance: should knowfreq 22%

answer

  1. one member left out
  2. absent is not the same as null
  3. silence even on error
  4. batches obey the same rule

basics

~20 s

A JSON-RPC 2.0 notification is a Request object with no id member at all. The server MUST NOT reply to it — not on success, not on error, not inside a batch — so the client never sees errors such as invalid params.

solid answer

~40 s

A notification is a Request object without an `id` member; leaving `id` out signals that the client has no interest in a Response. The server MUST NOT reply — not on success, not on error, not inside a batch — so the specification itself calls notifications not confirmable: the client never learns of an `Invalid params` or an `Internal error`. The test is absence, not null: `"id": null` is a legal, if discouraged, request id that does get a Response. Notifications suit fire-and-forget signals such as progress or log events; anything whose outcome matters should be a call with an `id`. JSON-RPC 1.0 marked notifications differently, with `id` set to `null`, which is one reason 2.0 discourages null ids.

go deeper

for a junior

Recall that a notification is a request with no id member and that the server never answers it, whether it succeeds or fails.

for a middle

Explain absent versus null id, why the specification calls notifications not confirmable, and how notifications behave inside a batch, including the all-notification case.

for a senior

Judge which messages in a real integration may safely be notifications, and explain how a silent drop after a server change would be noticed when the protocol itself reports nothing.

for a principal

Set a rule for an estate on when fire-and-forget is acceptable, weighing the saved round trip against the operational cost of failures nobody on the calling side can see.

## The one-member difference In JSON-RPC 2.0 a **notification** is a Request object without an `id` member. Everything else is the same as a call: `jsonrpc` exactly `"2.0"`, a `method`, and optional `params` as an Array or an Object. Leaving the `id` out signals, in the specification's words, the Client's lack of interest in the corresponding Response object. ```json {"jsonrpc": "2.0", "method": "progress.update", "params": {"done": 40, "total": 120}} ``` There is no flag, no special method name and no separate object type; the absence of one member is the whole mechanism. ## What the server must not do The rule is unconditional: the Server **MUST NOT reply to a notification**, including notifications inside a batch request. In practice: - **On success** — no Response. - **On failure** — an unknown method, params that do not fit, a crash inside the method — still no Response. - **Inside a batch** — no Response object for that element in the reply Array; and if every element of the batch was a notification, the Server returns nothing at all, because it MUST NOT return an empty Array. ## Why failures are invisible The specification draws the consequence itself: notifications are **not confirmable by definition**, since they have no Response object, so the Client is not aware of errors such as "Invalid params" or "Internal error". What that means for a running integration: 1. A typo in the method name fails silently. A call would have come back with -32601 Method not found; the notification simply vanishes. 2. A Server release that tightens parameter validation turns notifications that used to work into silent drops, with nothing on the Client's side to show it. 3. Only the Server's own records — its logs or metrics — can reveal the failure, and that is the Server's business, not the protocol's. So the choice between a notification and a call is a choice about whether the Client needs to know the outcome, not about whether it needs the result. ## Absent, null, or a value | `id` in the Request | What it is | What the Server sends | |---|---|---| | absent | a notification | nothing, ever | | `null` | a call (discouraged) | a Response whose `id` is null | | a String or Number | a call | a Response echoing that `id` | The middle row is the trap. The 2.0 specification allows Null as an `id` value but says it SHOULD normally not be used, for two reasons it states: the Server uses a null `id` in Responses when it could not determine the request's `id`, and **JSON-RPC 1.0 used a null `id` for notifications**. A client that writes `"jsonrpc": "2.0"` but keeps 1.0's habit of `"id": null` for notifications will get answers it never expected. ## Objects that merely lack an id Not every object without an `id` is a notification. A notification is a *valid* Request without an `id`; an object that is not a valid Request is an error. The specification's own examples show it: - `{"jsonrpc": "2.0", "method": 1, "params": "bar"}` — no `id`, but `method` is not a String and `params` is not Structured — is answered with `-32600 Invalid Request` and an `id` of null. - Inside a batch, the element `{"foo": "boo"}` gets its own `-32600` Response with a null `id`. A Server that treated every id-less object as a silent notification would hide malformed traffic that the specification expects it to report. ## Choosing between a notification and a call - **Notification:** progress updates, log lines, telemetry, "something changed" hints, where losing one is harmless and the next one supersedes it. - **Call with an `id`:** anything that changes state the Client relies on, anything that can be rejected for bad input, and anything whose failure someone must act on — even if the `result` will be ignored. - **Over a transport that pairs requests with responses**, such as HTTP, the transport may still need to answer something even though JSON-RPC sends no Response; what that is the carrying protocol's or the implementation's decision, since the 2.0 specification defines no HTTP mapping. A notification is cheaper only in the sense that nobody waits; it buys that by giving up every signal about what happened.

  • If a JSON-RPC 2.0 client needs to know a call succeeded but has no use for its result, should it still send an id?
    Yes. The id, not the usefulness of the result, is what makes the server answer. A request with an id gets a Response with either result or error, so the client at least learns about failures such as -32602 Invalid params; a notification leaves it nothing to wait for and nothing to inspect.
  • What should a JSON-RPC 2.0 server do with a notification that names a method it does not have?
    Send nothing. For a call this would be -32601 Method not found, but the server MUST NOT reply to a notification, so the failure can only be recorded on the server's side, for example in its own logs. The client stays unaware, exactly as the specification warns.

A notification is a postcard with no return address: the recipient may act on it, but even if the card is unreadable there is nowhere to send a reply, so the sender learns nothing either way.

saying these in an interview costs you the question

  • A JSON-RPC 2.0 notification is a request whose id is set to null.
  • The server still sends an error response when a notification fails.
  • Inside a batch, each notification gets an empty placeholder response.
  • Any object without an id, even a malformed one, is silently ignored as a notification.
  • A notification is fine for any call whose result the client ignores.