hcengineering/platform · error
Client ${clientId as string} not found
Error message
Client ${clientId as string} not found What it means
BackRPC server's send() pushes a one-way event to a connected client, but clientId has no entry in clientMapping, so no transport identity exists to deliver to. It throws instead of silently dropping the event. Same root cause as request(): unknown or disconnected client.
Source
Thrown at foundations/net/packages/backrpc/src/server.ts:331
if (clientIdentity === undefined) {
throw new Error(`Client ${clientId} not found`)
}
return await new Promise<any>((resolve, reject) => {
const reqId = clientId + '-' + this.requestCounter++
this.backRequests.set(reqId, { resolve, reject })
void this.doSend([clientIdentity, backrpcOperations.request, reqId, stringifyJSON([method, params])]).catch(
(err) => {
reject(err)
}
)
})
}
async send (clientId: ClientT, body: any): Promise<any> {
const clientIdentity = this.clientMapping.get(clientId)
if (clientIdentity === undefined) {
throw new Error(`Client ${clientId as string} not found`)
}
await this.doSend([clientIdentity, backrpcOperations.event, '', stringifyJSON(body)])
}
async close (): Promise<void> {
this.closed = true
this.stopTick?.()
this.router.close()
}
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Prune stale clientIds from your registry on disconnect events before sending
- Re-establish the client connection and resend the event
- Wrap sends in try-catch and treat unknown-client as a disconnect signal
- Confirm the client connected to the same server instance handling the send
Example fix
// before
await server.send(clientId, { type: 'notify' })
// after
try {
await server.send(clientId, { type: 'notify' })
} catch (e) {
removeClient(clientId) // stale; drop or reconnect
} Defensive patterns
Strategy: try-catch
Validate before calling
// skip sends for clients no longer tracked if (!liveClients.has(clientId)) return
Type guard
function canSend(mapping: Map<ClientT, unknown>, clientId: ClientT): boolean {
return mapping.get(clientId) !== undefined
} Try / catch
try {
await server.send(clientId, body)
} catch (e) {
if (e instanceof Error && e.message.includes('not found')) {
removeClient(clientId)
} else { throw e }
} Prevention
- Prune client lists on disconnect
- Avoid post-close final event sends
- Treat unknown-client as disconnect signal in broadcast loops
- Ping clients before relying on stale ids
When it happens
Trigger: Calling server.send(clientId, body) for a clientId that never connected, already disconnected, or connected to a different server instance.
Common situations: Broadcast loops that iterate a cached client list without pruning disconnected ids; sending a final event after the client's close completed; restarting the server while clients reconnect with new ids.
Related errors
- Client ${clientId} not found
- Wrong video options specified
- platform.status.ConnectionClosed
- HTTP error ${res.status}
- result.error
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/da1bcab0aa3cab1c.
Report an issue: GitHub.