Protocol¶
The RPC server speaks JSON-RPC 2.0 with newline-delimited framing. This page specifies the framing, the two message objects, and how a connection begins and ends. Methods covers what you can ask for, and Errors covers what comes back when a request fails.
Framing¶
Each message is one JSON object encoded as UTF-8 on a single line, terminated by a newline. This applies in both directions. Nothing spans lines, so a client reads a response by reading one line.
The server writes compact JSON with no insertions of its own. It writes protocol lines to standard output and nothing else, so anything a client reads from that stream is a response. Diagnostics and startup errors go to standard error.
Reading is tolerant in three ways:
- Lines may end
\nor\r\n. Trailing whitespace is trimmed before parsing, so a client on Windows does not have to strip line endings itself. - Blank lines are skipped rather than treated as malformed input.
- A line that is not valid UTF-8 fails as a parse error for that line alone. It does not end the connection.
Requests are not required to be pretty-printed or compact in any particular way, as long as each one occupies exactly one line. The RPC Server implementation triggers a flush of the pipe per response output.
The request object¶
jsonrpc- required, and must be exactly the string"2.0". Any other value is an invalid request.method- required. The name of the method to call, as listed in Methods.params- optional. A JSON object of named parameters. Omit it, or pass{}, to use a method's defaults. It must be an object; see Parameters are named below.id- optional. A number or a string. Omit it to send a notification.
The response object¶
jsonrpc- always the string"2.0".result- present only on success. Its shape depends on the method; see Methods.error- present only on failure; see Errors.id- the request'sid, echoed back.
Exactly one of result and error is present. Neither key appears with a null value, so testing for the presence of error is a reliable success check.
Correlating responses with requests¶
A client matches a response to its request by id, never by the order the lines arrive in.
An id is echoed back exactly as it was sent, including its JSON type. Both numbers and strings are permitted, and numeric ids are preserved faithfully, including values above 2^63 and values with a fractional part. Use whatever your client finds natural; a monotonically increasing integer is the usual choice.
An id that the server never reads, because the line failed to parse, comes back as null. See Errors for which failures can still recover the id and which cannot.
Notifications¶
A request with no id is a notification. The server performs the call and sends nothing back, whether it succeeded or failed.
An explicit "id": null is also a notification. JSON-RPC 2.0 permits a null id on an ordinary request, but this server treats the two spellings as the same thing. Send an id whenever you want an answer.
A notification that fails fails silently
Because no response is sent, a notification that names an unknown method or has bad parameters produces nothing at all. Use notifications only where you do not need to know the outcome, and prefer an ordinary request while developing a client.
Differences from JSON-RPC 2.0¶
The server departs from the specification in two places, both deliberate.
Batches are not supported¶
A line whose top-level JSON is an array is rejected. Send each request on its own line instead: writing several lines before reading any responses gets the same effect as a batch, and the id on each response tells you which request it belongs to.
Parameters are named¶
params must be a JSON object. The positional array form that JSON-RPC permits is rejected, so the order of a method's parameters is never part of this API and can change without breaking a client.
Parameter names on the wire are the CLI's long flag names with hyphens replaced by underscores: --skip-scan becomes skip_scan. Unknown names are rejected rather than ignored, which turns a typo into an immediate error instead of a silently defaulted parameter.
The workspace¶
A server operates on exactly one workspace for the whole of its life, chosen when it starts by fxv rpc. Three consequences matter to a client:
- No request can change it. A request that includes a
working_dirparameter is rejected, whatever the method. To work with two workspaces, run two servers. - A bad one fails at startup rather than per request. See Startup failures below.
- It is re-read on every request. Changes made by another process, including
fxvcommands run from a shell, are visible to the next call without restarting the server.
The connection lifecycle¶
There is no handshake. The server is ready to accept requests as soon as it starts, and a client may send its first request immediately. server.info is available for discovering the method set, but calling it is optional.
A connection ends in one of three ways:
- End of input. The client closes the server's standard input. The server finishes the request in flight and exits.
- A
shutdowncall. The server answers the request, then ends the connection. The response is written and flushed first, so a client that sent anidalways receives the acknowledgement. - A closed pipe. The client goes away while the server is writing. The server stops rather than failing.
All three exit 0. An exit code other than 0 means the server never started; see Startup failures below.
A shutdown that the server rejects, such as one that includes a working_dir parameter, does not end the connection. The connection ends only on a shutdown that succeeded.
Startup failures¶
A server that cannot start produces no JSON-RPC error, because there is no connection to send it on. It writes the reason to standard error and exits non-zero, having written nothing to standard output.
A stream that closes immediately therefore means a startup failure, not an empty response. Read standard error to find out why. The causes are a --working-dir that is not part of a workspace, and a global option the protocol cannot support; fxv rpc lists which options those are and how each is treated.