Skip to content

[Bug] Reject batch_size = 0 in indexer-grpc data-service-v2 streams #19882

Description

@fallintoplace

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:

  1. Historical path: batch_size = 0 reaches transactions.chunks(max_num_transactions_per_batch), which panics when the fetched transaction batch is non-empty.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions