Querying canisters with protobuf

I’m trying to query the registry canister using protobuf but getting stuck on encoding. I’m using protobufjs, @dfinity/agent, and the .proto files from ic:

const argType = root.lookupType("ic_registry_transport.pb.v1.RegistryGetValueRequest")
const retType = root.lookupType("ic_registry_transport.pb.v1.RegistryGetValueResponse")
const emptyArg = argType.encode({}).finish(); // <Buffer >

const result = await agent.query("rwlgt-iiaaa-aaaaa-aaaaa-cai", 
  { methodName: "get_value", emptyArg }
retType.decode(result.reply.arg) // valid RegistryGetValueResponse {..}

With an empty arg, the request is valid and accepted by the canister. However, when I try with real args, I get an error:

const arg = argType.encode({ key: Buffer.from("test") }).finish(); // <Buffer 12 04 74 65 73 74>
// returns the following:
RegistryGetValueResponse {
  error: RegistryError {
    code: 1,
    reason: 'Registry Canister Error. Msg: PB error: failed to decode Protobuf message: unexpected end group tag'

According to this decoder, my input 120474657374 is valid.

Any ideas? @PaulLiu or @hansl maybe?


Well, turns out it was a JS type error. I was cbor-encoding a UInt8Array instead of a Buffer. Fixed here: Ensure arg is buffer · ic-cubes/[email protected] · GitHub

The question above is solved! New question:

Is there an official protobuf canister service definition?

I am currently handling annotations like this:

service MyCanister {
  rpc read (google.protobuf.Empty) returns (google.protobuf.UInt64Value) {
    option annotation = query;

  rpc write (google.protobuf.UInt64Value) returns (google.protobuf.Empty) {
    option annotation = update;
1 Like