Large Java Ledger API gRPC messages and RESOURCE_EXHAUSTED


I was playing around with the Java Ledger API and I submitted a request to the CommandSubmissionService with a large payload, which was accepted by the CommandCompletionService.

However, when attempting to fetch the contract using the ActiveContractService, we find that we receive the error RESOURCE_EXHAUSTED: gRPC message exceeds maximum size 4194304: 5000618

This is a major problem for us as we use the ActiveContractService to cleanup and archive a user’s contracts, but we can’t archive the contracts since we can’t retrieve the contracts and we don’t have the ContractId. Furthermore, since we can only filter the ActiveContractService by party, we can no longer use the ActiveContractService for the submitter. The only resolution is to manually reset the ledger, which is not possible on a non-sandbox ledger.

Ideally, if a contract would be unable to be retrieved by the ActiveContractService, then it should not be accepted by the CommandCompletionService and/or CommandSubmissionService.

Any suggestions?

To replicate:
We have a simple smart contract of the form:

module SimpleOwnership where

import DA.Next.Set (Set)

template SimpleOwnership
    a : Party
    obs : Set Party
    note : Text
    signatory a
    observer obs
    ensure note /= "BadNote" || note /= "Yes"

Our command for the request only contains:
commandList.add(new SimpleOwnership(signatory, new Set<>(observerMap), args).create());
Where signatory is “Bob”, observerMap is empty and args is a String of length 5,000,000.

1 Like


the sandbox has an option --max-inbound-message-size that can push this limit out. It seems to me that this flag belongs to the gRPC implementation. So, while I am not sure which component is creating this issue for you, you may be able to use the same flag to fix this for you.



Note that it is an inbound message size. So if you fail to fetch contracts, you need to bump the maximum inbound size on your client not on the ledger. That’s also why the ledger has no way of preventing those contracts from being created.

For the Java bindings, you can do that using something like

NettyChannelBuilder nettyBuilder = NettyChannelBuilder.forAddress(host, port).maxInboundMetadataSize(bytes);
DamlLedgerClient damlLedgerClient = DamlLedgerClient.newBuilder(nettyBuilder).build();

Oh thanks! Changing it to maxInboundMessageSize instead of maxInboundMetadataSize and it worked for us.