From 25dd42503b2cb8acad2e1e442b480eef44ea2cc8 Mon Sep 17 00:00:00 2001 From: Mavis Date: Tue, 2 Jun 2026 23:29:04 +0000 Subject: [PATCH] fix: wrap stream handshake decode in try/catch + raw-bytes diagnostic The original fix only wrapped the RPC handshake decode. The user's symptom is the same error after the RPC handshake succeeds (the kRPC server registers the client on the RPC side), so the failure must be in the stream handshake. Added: - try/catch around the stream decode (matching the RPC decode) - KRPC_DEBUG env var that dumps raw bytes from both handshakes to the console. Set it to 1 when running the bridge to see exactly what kRPC is sending: KRPC_DEBUG=1 pnpm start Output will include lines like: [krpc-client] rpc handshake raw response (17 bytes): 08001200... [krpc-client] stream handshake raw response (4 bytes): 08001200 --- packages/krpc-client/src/client.ts | 34 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/krpc-client/src/client.ts b/packages/krpc-client/src/client.ts index 3a8525d..1d7f6fd 100644 --- a/packages/krpc-client/src/client.ts +++ b/packages/krpc-client/src/client.ts @@ -106,11 +106,19 @@ export class KRPCClient { }); let resp: { status: number | string; message: string; clientIdentifier: Uint8Array }; try { + const rpcRaw = await recvRawMessage(this.rpcSocket); + if (process.env.KRPC_DEBUG) { + // eslint-disable-next-line no-console + console.log( + '[krpc-client] rpc handshake raw response (' + rpcRaw.length + ' bytes):', + Buffer.from(rpcRaw).toString('hex'), + ); + } resp = decodeMessage<{ status: number | string; message: string; clientIdentifier: Uint8Array; - }>(KRPC.ConnectionResponse, await recvRawMessage(this.rpcSocket)); + }>(KRPC.ConnectionResponse, rpcRaw); } catch (e) { throw new Error(`kRPC RPC handshake (response decode) failed: ${formatErr(e)}`); } @@ -136,10 +144,26 @@ export class KRPCClient { type: 1, // STREAM clientIdentifier: this.clientIdentifier, }); - const streamResp = decodeMessage<{ status: number | string; message: string }>( - KRPC.ConnectionResponse, - await recvRawMessage(this.streamSocket), - ); + let streamResp: { status: number | string; message: string }; + try { + const streamRaw = await recvRawMessage(this.streamSocket); + // Diagnostic: log the raw bytes for the stream handshake response + // so we can see what the kRPC server actually sent. Useful when + // debugging "Cannot read properties of null" type errors. + if (process.env.KRPC_DEBUG) { + // eslint-disable-next-line no-console + console.log( + '[krpc-client] stream handshake raw response (' + streamRaw.length + ' bytes):', + Buffer.from(streamRaw).toString('hex'), + ); + } + streamResp = decodeMessage<{ status: number | string; message: string }>( + KRPC.ConnectionResponse, + streamRaw, + ); + } catch (e) { + throw new Error(`kRPC Stream handshake (response decode) failed: ${formatErr(e)}`); + } if (streamResp.status !== 'OK' && streamResp.status !== 0) { throw new Error(`Stream handshake failed: ${streamResp.status} ${streamResp.message}`); }