Message Protocol
This page documents the low-level message protocol used over the MessagePort. You do not need to know this to use the library, but it is useful for debugging or building custom integrations.
Client to Server Messages
Section titled “Client to Server Messages”Request
Section titled “Request”Sent when the client initiates a query, mutation, or subscription.
interface TRPCPortRequest { kind: 'request'; id: number; method: 'query' | 'mutation' | 'subscription'; path: string; input: unknown; lastEventId?: string;}| Field | Type | Description |
|---|---|---|
kind | 'request' | Message discriminator |
id | number | Unique request identifier (monotonically increasing) |
method | 'query' | 'mutation' | 'subscription' | The tRPC procedure type |
path | string | Dot-separated procedure path (e.g., 'user.getById') |
input | unknown | The procedure input, transferred via Structured Clone |
lastEventId | string | undefined | For subscription resumption (optional) |
Subscription Stop
Section titled “Subscription Stop”Sent when the client unsubscribes from an active subscription.
interface TRPCPortSubscriptionStop { kind: 'subscription.stop'; id: number;}| Field | Type | Description |
|---|---|---|
kind | 'subscription.stop' | Message discriminator |
id | number | The ID of the subscription to stop |
Server to Client Messages
Section titled “Server to Client Messages”Result (Data)
Section titled “Result (Data)”Sent when a procedure returns data or a subscription yields a value.
interface TRPCPortResultData { kind: 'result'; id: number; type: 'data'; data: unknown; eventId?: string;}| Field | Type | Description |
|---|---|---|
kind | 'result' | Message discriminator |
id | number | The request ID this result belongs to |
type | 'data' | Result type discriminator |
data | unknown | The procedure result, transferred via Structured Clone |
eventId | string | undefined | The tracked event ID for resumable subscription data |
For queries and mutations, a single data result is sent, and the request is complete.
For subscriptions, multiple data results may be sent over time.
When a subscription yields tracked(id, data), the protocol sends eventId: id and data: { id, data }, matching tRPC v11’s tracked subscription output shape.
Result (Started)
Section titled “Result (Started)”Sent after a subscription procedure has started successfully.
interface TRPCPortResultStarted { kind: 'result'; id: number; type: 'started';}| Field | Type | Description |
|---|---|---|
kind | 'result' | Message discriminator |
id | number | The subscription ID |
type | 'started' | Indicates the subscription has started |
Result (Stopped)
Section titled “Result (Stopped)”Sent when a subscription ends naturally (the async iterable completes).
interface TRPCPortResultStopped { kind: 'result'; id: number; type: 'stopped';}| Field | Type | Description |
|---|---|---|
kind | 'result' | Message discriminator |
id | number | The subscription ID |
type | 'stopped' | Indicates the subscription has ended |
Sent when a procedure throws an error.
interface TRPCPortError { kind: 'error'; id: number; error: { code: number; message: string; data: unknown; };}| Field | Type | Description |
|---|---|---|
kind | 'error' | Message discriminator |
id | number | The request ID that caused the error |
error.code | number | tRPC error code (matches HTTP status codes) |
error.message | string | Human-readable error message |
error.data | unknown | Additional error metadata (tRPC error shape data) |
Message Flow Examples
Section titled “Message Flow Examples”Client Server | | | { kind: 'request', | | method: 'query', | | id: 1, path, input } | |------------------------------>| | | | { kind: 'result', | | id: 1, type: 'data', | | data } | |<------------------------------|Subscription
Section titled “Subscription”Client Server | | | { kind: 'request', | | method: 'subscription', | | id: 1, path, input } | |------------------------------>| | | | { kind: 'result', | | id: 1, type: 'started' } | |<------------------------------| | { kind: 'result', | | id: 1, type: 'data', ..} | |<------------------------------| | { kind: 'result', | | id: 1, type: 'data', ..} | |<------------------------------| | | | { kind: 'subscription.stop',| | id: 1 } | |------------------------------>| | | | // Or, if the async iterable | | // completes naturally: | | { kind: 'result', | | id: 1, type: 'stopped' } | |<------------------------------|