-
Notifications
You must be signed in to change notification settings - Fork 14
Description
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
- Create a gRPC server that returns a response larger than 10 MB (e.g. a block with TSS Wrap
items totalling ~30 MB). - Create a
PbjGrpcClientConfigwithmaxSize = 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);
- Issue a
createCalland 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 passedPbjGrpcDatagramReader.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-helidon0.14.1- Blocks receiving any single gRPC message > 10 MB, regardless of
maxSizeconfiguration.
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