0

I have a gRPC server using the grpc-java library. Sometimes a call to the server is closed with and error status INTERNAL which is valued 13, and the description Half-closed without a request.

I found this other question that seems similar, but there it was said that the code was calling onComplete() before calling onNext(), and my endpoint actually works just fine, this error happens very sporadically given the number of calls it responds.

Looking at the implementation of UnaryServerCallListener it seems that the only way that something like this could happen is if the request received on onMessage is null.

@Override
      public void onMessage(ReqT request) {
        if (this.request != null) {
          // Safe to close the call, because the application has not yet been invoked
          call.close(
              Status.INTERNAL.withDescription(TOO_MANY_REQUESTS),
              new Metadata());
          canInvoke = false;
          return;
        }

        // We delay calling method.invoke() until onHalfClose() to make sure the client
        // half-closes.
        this.request = request;
      }

      @Override
      public void onHalfClose() {
        if (!canInvoke) {
          return;
        }
        if (request == null) {
          // Safe to close the call, because the application has not yet been invoked
          call.close(
              Status.INTERNAL.withDescription(MISSING_REQUEST),
              new Metadata());
          return;
        }

        method.invoke(request, responseObserver);
        request = null;
        responseObserver.freeze();
        if (wasReady) {
          // Since we are calling invoke in halfClose we have missed the onReady
          // event from the transport so recover it here.
          onReady();
        }
      }

What could cause the request to be missing ?

  • If the client doesn't call `sendMessage` and just calls `halfClose` after starting the call? – San P Sep 13 '20 at 18:18
  • Agree with San's opinion. For unary RPCs, the service is expected to receive exactly one request. The ServerCallListener can get notified with `halfClosed` before receiving any request message if the client side half-closes the stream (aka, ClientCall) before any requests message is sent. This can happen when the client called `StreamObserver.onComplete()` before `StreamObserver.onNext()`. – voidzcy Sep 17 '20 at 21:12

0 Answers0