Skip to content

PBJ Bug: PbjGrpcClientConfig.maxSize Not Respected by PbjGrpcDatagramReader #756

@AlfredoG87

Description

@AlfredoG87

Description

Summary

PbjGrpcClientConfig accepts a maxSize parameter (introduced in 0.14.1) intended to allow
clients to receive gRPC responses larger than Codec.DEFAULT_MAX_SIZE (2 MB). However, the
PbjGrpcDatagramReader — which accumulates incoming HTTP/2 DATA frames on the client side —
has a hardcoded MAX_BUFFER_SIZE = 10_485_760 (10 MB) that is never overridden by the
configured maxSize. As a result, any response payload larger than 10 MB throws a
java.nio.BufferOverflowException regardless of the value passed to PbjGrpcClientConfig.

Steps to Reproduce

  1. Create a gRPC server that returns a response larger than 10 MB (e.g. a block with TSS Wrap
    items totalling ~30 MB).
  2. Create a PbjGrpcClientConfig with maxSize = 37_748_736 (36 MB):
    new PbjGrpcClientConfig(
        Duration.ofMillis(10_000),
        Tls.builder().enabled(false).build(),
        Optional.of(""),
        "application/grpc",
        GrpcCompression.IDENTITY,
        GrpcCompression.getDecompressorNames(),
        37_748_736);
  3. Issue a createCall and stream the large response.

Expected: The call succeeds; the response is parsed up to the configured 36 MB limit.
Actual: java.nio.BufferOverflowException in PbjGrpcDatagramReader.ensureCapacity.

Root Cause

In PbjGrpcCall.receiveRepliesLoop, the datagram reader is always constructed with the
no-arg constructor:

// PbjGrpcCall.receiveRepliesLoop (decompiled from pbj-grpc-client-helidon-0.14.1.jar)
PbjGrpcDatagramReader reader = new PbjGrpcDatagramReader();  // maxSize never passed

PbjGrpcDatagramReader.ensureCapacity enforces a hardcoded ceiling:

// PbjGrpcDatagramReader (decompiled — MAX_BUFFER_SIZE = 10_485_760)
if (newCapacity > 10_485_760) {
    throw new BufferOverflowException();
}

The maxSize field on PbjGrpcClientConfig is never read in PbjGrpcCall or
PbjGrpcDatagramReader.

Existing Test That Passes (But Only Because Payload < 10 MB)

The test testUnaryMethodReceivingExtraLargePayload in the PBJ test suite passes because
Codec.DEFAULT_MAX_SIZE * 2 = 4_194_304 (4 MB), which is under the 10 MB cap:

final String extraLongString = "a".repeat(Codec.DEFAULT_MAX_SIZE * 2); // 4 MB — under 10 MB cap
final GrpcClient grpcClient = GrpcTestUtils.createGrpcClient(
    port.port(),
    GrpcTestUtils.PROTO_OPTIONS,
    GrpcCompression.IDENTITY,
    GrpcCompression.getDecompressorNames(),
    Codec.DEFAULT_MAX_SIZE * 2);

The same test would fail if the payload were, say, Codec.DEFAULT_MAX_SIZE * 10 (20 MB).

Suggested Fix

Pass maxSize from PbjGrpcClientConfig into PbjGrpcDatagramReader:

// In PbjGrpcCall constructor or receiveRepliesLoop:
PbjGrpcDatagramReader reader = new PbjGrpcDatagramReader(config.maxSize());

And update PbjGrpcDatagramReader to use the provided limit instead of the hardcoded constant:

// PbjGrpcDatagramReader
private final int maxBufferSize;

PbjGrpcDatagramReader(int maxBufferSize) {
    this.maxBufferSize = maxBufferSize;
}

private void ensureCapacity(int required) {
    // ...
    if (newCapacity > maxBufferSize) {
        throw new BufferOverflowException();
    }
    // ...
}

Affected Version

  • pbj-grpc-client-helidon 0.14.1
  • Blocks receiving any single gRPC message > 10 MB, regardless of maxSize configuration.

Workaround

None available within PBJ 0.14.1. Callers needing > 10 MB responses must wait for a fix or
send large payloads in multiple smaller gRPC frames (< 10 MB each).

Steps to reproduce

Repeat the Test with a 36MB size message

Additional context

No response

Hedera network

No response

Version

v0.14.1

Operating system

None

Metadata

Metadata

Labels

BugAn error that causes the feature to behave differently than what was expected based on design.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions