deepseek-ai/deepseek-harness · error
rpcId mismatch for ${endpoint}: sent ${rpcId}, got ${full.rp
Error message
rpcId mismatch for ${endpoint}: sent ${rpcId}, got ${full.rpcId} What it means
Every unary call mints a random UUID rpcId, sends it inside the client-request envelope, and requires the server response envelope to echo it. A mismatch means the envelope answers a different request: typically a caching proxy or service worker replaying a stale response, an interleaving middlebox, or a server implementation that mints its own id instead of echoing the request's.
Source
Thrown at packages/client/connection/src/client/rpc.ts:49
rpcId,
method: endpoint,
payload,
}
const response = await send(
new URL(`${channel}/${endpoint}`, resolveBase()),
{
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(message),
...signal === undefined ? {} : { signal },
},
)
if (!response.ok) {
throw new Error(`transport failure for ${channel}/${endpoint}: HTTP ${response.status}`)
}
const full = serverResponseSchema.parse(await response.json())
if (full.rpcId !== rpcId) {
throw new Error(`rpcId mismatch for ${endpoint}: sent ${rpcId}, got ${full.rpcId}`)
}
return full.result
},
}
}
function resolveBase(): string {
const location = (globalThis as { location?: { origin?: string } }).location
return location?.origin !== undefined && location.origin !== 'null' ? location.origin : INTERNAL_BASE
}
function assertTarget(channel: string, endpoint: string): void {
const segments = endpoint.split('/')
if (!CHANNEL_PATTERN.test(channel)
|| segments.some(segment =>
segment === '' || segment === '.' || segment === '..' || !ENDPOINT_SEGMENT_PATTERN.test(segment))) {
throw new Error(`connection: invalid RPC target ${JSON.stringify(`${channel}/${endpoint}`)}`)
}View on GitHub (pinned to b150a551b8)
Solutions
- If you control the server, echo the request envelope's rpcId verbatim instead of minting one
- Disable HTTP and service-worker caching for the /api paths the RPC posts to
- Retry the call once with a fresh id when the operation is idempotent; the stale cached envelope is usually evicted by then
Example fix
// before — server builds its own id
const response = { type: 'server-response', rpcId: RpcId(randomUuid()), result }
// after — echo the request's id
const response = { type: 'server-response', rpcId: request.rpcId, result } Defensive patterns
Strategy: retry
Try / catch
async function callRetrying(rpc, channel, endpoint, payload, attempts = 2) {
for (let i = 0; ; i++) {
try {
return await rpc.call(channel, endpoint, payload)
} catch (error) {
if (i + 1 >= attempts || !String(error).includes('rpcId mismatch')) throw error
}
}
} Prevention
- Never cache RPC POST responses; exclude /api from service-worker fetch handlers
- Always echo the request's rpcId in server envelopes
- Mint a fresh correlation id per attempt; never reuse ids across retries
When it happens
Trigger: rpc.call receives a schema-valid response whose rpcId differs from the sent one: HTTP or service-worker caches replaying an old POST response, a proxy mis-correlating concurrent requests, or a hand-written server that forgets to copy rpcId from request to response.
Common situations: A service worker or CDN configured to cache the RPC POST route; devtools offline-replay; a custom server generating fresh ids in the response envelope.
Related errors
- context-not-found
- transport failure for ${channel}/${endpoint}: HTTP ${respons
- session create failed: ${rpcError.code}: ${rpcError.message}
- session fork failed: ${rpcError.code}: ${rpcError.message}
- fork child rename failed: ${renamed.error.code}: ${renamed.e
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/8879a23520766791.
Report an issue: GitHub.