Bug
GetTransactionsRequest.batch_size is accepted as-is in both the historical and live paths of indexer-grpc-data-service-v2, and Some(0) is not rejected.
That creates two runtime failure modes:
- Historical path:
batch_size = 0 reaches transactions.chunks(max_num_transactions_per_batch), which panics when the fetched transaction batch is non-empty.
- Live path:
batch_size = 0 makes the in-memory cache loop stop immediately, returns an empty result with version - 1 as last_processed_version, and can cause invalid processed ranges / no forward progress in the stream.
Affected code
Historical request handling:
ecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/historical_data_service.rs
Live request handling:
ecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/live_data_service/mod.rs
ecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/live_data_service/in_memory_cache.rs
Proto definition:
protos/proto/aptos/indexer/v1/raw_data.proto
Verified behavior
Historical path:
request.batch_size is converted directly to usize
- later used in
transactions.chunks(max_num_transactions_per_batch)
chunks(0) panics
Live path:
request.batch_size is converted directly to usize
- cache loop condition includes
result.len() < max_num_transactions_per_batch
- with
0, the loop never executes, no version is consumed, and the function returns version - 1
- the stream then uses that as
last_processed_version and advances with last_processed_version + 1
Expected behavior
Requests with batch_size = 0 should be rejected immediately with Status::invalid_argument(...) before a stream task is spawned.
Suggested fix
Add explicit validation to both historical and live request handling, e.g.:
let max_num_transactions_per_batch = match request.batch_size {
Some(0) => {
let err = Err(Status::invalid_argument("batch_size must be greater than 0."));
let _ = response_sender.blocking_send(err);
continue;
},
Some(batch_size) => batch_size as usize,
None => DEFAULT_MAX_NUM_TRANSACTIONS_PER_BATCH,
};
The live service should perform the same validation before calling start_streaming(...).
Notes
The proto comment also says values larger than 1000 should be rejected, but that appears to be a separate validation gap. This issue is specifically about the batch_size = 0 runtime bug.
Bug
GetTransactionsRequest.batch_sizeis accepted as-is in both the historical and live paths ofindexer-grpc-data-service-v2, andSome(0)is not rejected.That creates two runtime failure modes:
batch_size = 0reachestransactions.chunks(max_num_transactions_per_batch), which panics when the fetched transaction batch is non-empty.batch_size = 0makes the in-memory cache loop stop immediately, returns an empty result withversion - 1aslast_processed_version, and can cause invalid processed ranges / no forward progress in the stream.Affected code
Historical request handling:
ecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/historical_data_service.rsLive request handling:
ecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/live_data_service/mod.rsecosystem/indexer-grpc/indexer-grpc-data-service-v2/src/live_data_service/in_memory_cache.rsProto definition:
protos/proto/aptos/indexer/v1/raw_data.protoVerified behavior
Historical path:
request.batch_sizeis converted directly tousizetransactions.chunks(max_num_transactions_per_batch)chunks(0)panicsLive path:
request.batch_sizeis converted directly tousizeresult.len() < max_num_transactions_per_batch0, the loop never executes, no version is consumed, and the function returnsversion - 1last_processed_versionand advances withlast_processed_version + 1Expected behavior
Requests with
batch_size = 0should be rejected immediately withStatus::invalid_argument(...)before a stream task is spawned.Suggested fix
Add explicit validation to both historical and live request handling, e.g.:
The live service should perform the same validation before calling
start_streaming(...).Notes
The proto comment also says values larger than
1000should be rejected, but that appears to be a separate validation gap. This issue is specifically about thebatch_size = 0runtime bug.