#13063·grpc-java

channelz: ServerData `calls_failed` counter not incremented upon client cancellation

Author: jdcormieCreated Sep 17, 2026Updated Sep 17, 2026

What version of gRPC are you using?

HEAD

What did you expect to see?

Per grpc/channelz/v1/channelz.proto (ServerData):

proto

// ServerData is data for a specific Server.
message ServerData {
  ...
  // The number of incoming calls started on the server
  int64 calls_started = 2;
  // The number of incoming calls that have completed with an OK status
  int64 calls_succeeded = 3;
  // The number of incoming calls that have a completed with a non-OK status
  int64 calls_failed = 4;
  ...

When an incoming RPC terminates due to client cancellation, transport reset, or client-side deadline expiration, the call terminates with non-OK status (Status.CANCELLED). I expect this situation to be reflected in calls_failed.

What did you see instead?

calls_started increments when the call arrives at the server. However, when a call is cancelled by the client before the server application closes, neither calls_succeeded nor calls_failed is incremented.

Client cancellations or timeouts are not unusual. So on any long-lived server, calls_started - calls_succeeded - calls_failed grows larger and larger over time.

Steps to reproduce

For ServerCallImplTest.java

  @Test
  public void callTracer_clientCancelled_reportsCallFailed() {
    ServerStreamListenerImpl<Long> streamListener =
        new ServerCallImpl.ServerStreamListenerImpl<>(call, callListener, context);

    streamListener.closed(Status.CANCELLED);

    ServerStats.Builder afterBuilder = new ServerStats.Builder();
    serverCallTracer.updateBuilder(afterBuilder);
    ServerStats after = afterBuilder.build();
    assertEquals(1, after.callsStarted);
    assertEquals(0, after.callsSucceeded);
    assertEquals(1, after.callsFailed); // <--- Fails. Actual value is 0.
  }