fix: Type.code nested-enum bug blocks GetServices decode

The real root cause of the 'Cannot read properties of null (reading code)'
error was hiding in two places, not one. The first (ConnectionResponse
status) was fixed in the previous commit. This commit fixes the second:

The KRPC.Type message has a 'code' field of nested-enum type
'Type.TypeCode'. When protobufjs decodes a GetServices response
(which contains MANY Type messages inside Procedure.returnType
fields), it hits the same nested-enum default-value lookup bug
and throws the TypeError.

The fix is identical to the ConnectionResponse.status fix:
change the field type from the nested-enum reference to plain
'uint32'. The wire format is the same (varint), and our code in
services.ts reads raw integers from the typecode field anyway.

This error was happening OUTSIDE my top-level try/catch in
client.connect() — it was in loadServices, called from
adapter.connect(). The bridge's catch caught it, but the error
message was the raw 'Cannot read properties of null (reading code)'
because loadServices didn't wrap the error.

Now:
- The schema fix makes the decode actually succeed
- The adapter wraps any remaining loadServices errors with a
  clear 'kRPC loadServices (GetServices decode) failed:' prefix
  so the next failure mode is immediately actionable
This commit is contained in:
Mavis
2026-06-02 23:47:13 +00:00
parent a6ba6e6583
commit b1b78a06a3
2 changed files with 21 additions and 3 deletions
+11 -2
View File
@@ -64,8 +64,17 @@ export class KRPCAdapter {
return;
}
await this.client.connect();
const loaded = await loadServices(this.client);
this.services = loaded.services;
try {
const loaded = await loadServices(this.client);
this.services = loaded.services;
} catch (e) {
// loadServices calls client.invoke, which decodes the
// KRPC.GetServices response (a HUGE KRPC.Services message).
// If anything goes wrong decoding that, surface a clear
// error instead of the buried protobufjs TypeError.
const msg = e instanceof Error ? e.message : String(e);
throw new Error(`kRPC loadServices (GetServices decode) failed: ${msg}`);
}
}
async disconnect(): Promise<void> {
+10 -1
View File
@@ -204,8 +204,17 @@ const schemaJson = {
},
},
Type: {
// The `code` field on Type is a wire-varint enum
// (TypeCode = uint32 under the hood). We model it as a
// plain uint32 to dodge the protobufjs nested-enum
// default-value lookup bug that throws
// "Cannot read properties of null (reading 'code')"
// when decoding a Type message whose code field is
// present. Same fix as ConnectionResponse.status.
// The values stay as a nested TypeCode enum for
// documentation / programmatic lookup (in services.ts).
fields: {
code: { type: 'Type.TypeCode', id: 1 },
code: { type: 'uint32', id: 1 },
service: { type: 'string', id: 2 },
name: { type: 'string', id: 3 },
types: { rule: 'repeated', type: 'Type', id: 4 },