grpc-node icon indicating copy to clipboard operation
grpc-node copied to clipboard

Incorrect arguments passed on null Metadata argument

Open ksitze opened this issue 3 years ago • 1 comments

Given a service definition:

service ServiceApi {
    rpc Run(RunRequest) returns (RunResponse);
}

message RunRequest {
  string id = 1;
}

message RunResponse {
  string id = 1;
}

protoc (command line follows) generates the run_grpc_pb.d.ts file below:

OUT_DIR="declaration-files/proto"
PROTO_PATH="./proto"
PROTOC_GEN_GRPC_PATH="./node_modules/.bin/grpc_tools_node_protoc_plugin"
protoc \
    --plugin="protoc-gen-ts=${PROTOC_GEN_TS_PATH}" \
    --plugin=protoc-gen-grpc=${PROTOC_GEN_GRPC_PATH} \
    --js_out="import_style=commonjs,binary:${OUT_DIR}" \
    --ts_out="service=grpc-node,mode=grpc-js:${OUT_DIR}" \
    --grpc_out="grpc_js:${OUT_DIR}" \
    --proto_path="${PROTO_PATH}" \
    proto/run.proto
export class ServiceApiClient extends grpc.Client {
  constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);
  run(argument: run_pb.RunRequest, callback: grpc.requestCallback<run_pb.RunResponse>): grpc.ClientUnaryCall;
  run(argument: run_pb.RunRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<run_pb.MutationResponse>): grpc.ClientUnaryCall;
  run(argument: run_pb.RunRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<run_pb.RunResponse>): grpc.ClientUnaryCall; // note this line
}

If code calls the version of the run function marked with note this line above and passes null for the options argument then grpc_js will always throw the exception Error: Incorrect arguments passed.

const credentials = createGrpcCredentials(host);
const serviceClient = ServiceApi.createClient(host, credentials);
client.run(createRequest(), new grpc.Metadata(), null, (e, v) => {});

The problem appears to be that line 220 in client.ts forces options to be defined as an Object when it can also be null (at least according to the above function definition).

The correct test should probably be

        !(
          arg1 instanceof Metadata &&
          ((null === arg2) || (arg2 instanceof Object)) &&
          isFunction(arg3)
        )

A work around until this is fixed is to simply pass an empty object in place of null for the options parameter

client.run(createRequest(), new grpc.Metadata(), {}, (e, v) => {});

ksitze avatar Jul 01 '22 19:07 ksitze

Those generated TypeScript types are a little wrong. Those arguments are not nullable; instead you should omit them entirely. The alternate call signatures with fewer arguments allow you to do that.

The protoc-gen-ts plugin is not maintained by us, so you may want to file a bug with that tool.

murgatroid99 avatar Jul 06 '22 15:07 murgatroid99