Skip to content
Developer Preview

Exit classification

Two channels sit outside the JSON-RPC wire and are part of the contract anyway: the host’s stderr and its exit code. Under stdio they are the only evidence a client has when the protocol itself cannot speak — when the process dies before or instead of answering. This page gives the conceptual classification model a client author needs.

The host writes human-readable diagnostics to stderr — startup failures, panics, provider-transport errors — and the format is explicitly not a contract: it changes freely between releases and no conformance fixture asserts against it, so stderr must not be parsed.

The client is nonetheless obliged to capture and surface it: spawning the host with stderr routed to a null sink converts every startup failure into an unexplained silent hang, the single worst failure mode of this design. Make the captured stream reachable by a user diagnosing a failure — a log file, a devtools pane, or at minimum the last lines attached to the error shown. The obligation is to preserve the evidence, not to interpret it.

Exit codes: a small stable set with fixed meanings

Section titled “Exit codes: a small stable set with fixed meanings”

Unlike stderr, exit codes are a contract, because they are what a client branches on when the process dies. The classification:

  • 0 — clean shutdown. stdin closed, the drain completed, session-end records were written; treat the session as durably closed.
  • 1 — unhandled error. The host failed for a reason it could not express on the wire; surface the captured stderr — the session log is intact but has no session-end record.
  • 2 — usage error. Bad arguments to the serve command: a client bug or a version mismatch; do not retry.
  • 3 — configuration error. The host started but could not load a usable configuration, profile, or credential set; do not retry — the user must fix configuration, and stderr names what.
  • 4 — session lease unavailable. The requested session is owned by another live process: equivalent to the in-band sessionInUse error arriving before the handshake could carry it.
  • 5 — SDK surface unavailable. This build will not serve because the experimental SDK tier is switched off; no invocation of this binary will serve, so do not retry with different arguments.
  • Anything else, or a signal — crash. Includes OOM kills; no session-end record exists, and the next load of the log backstops the gap with a crash-inferred reason.

New codes may be added, but the meanings above never change; a client must treat an unrecognized non-zero code as the crash row rather than as a specific condition. That rule is what keeps a client built against a shorter list correct against a longer one: it reads a crash, surfaces the captured stderr, and the stderr says what actually happened.

The codes are separated by remedy, not by severity. Code 5 is deliberately not code 2, because a correctly-formed invocation of a build that will not serve is not a client bug, and the two have opposite remedies; it is also deliberately not code 3, because no configuration was read, so pointing the user at configuration would send them somewhere there is nothing to fix.

The crash row also closes the durability story: an orderly shutdown writes a durable session-end record before exiting, while a crash writes nothing by design, and the next load of the log infers what happened. So exit classification is not cosmetic — it tells the client whether the session was closed durably (code 0), left intact without a session-end record (code 1 and the crash row), or never opened at all (codes 2 through 5).

Host death is also the one named exception to the terminal guarantee: every item that starts is guaranteed exactly one terminal, and when the host dies abnormally the missing terminals are reconciled on the next resume rather than on the live connection. The fold model covers those mechanics. On an ephemeral host the reconciliation never runs, and abnormal host death obliges the client to treat still-open items as terminal-unknown and discard the session — see durability profiles.