apache/beam · error · SplitNotPossibleError

num_splits must be > 1, got

Error message

num_splits must be > 1, got: %d

What it means

Datastore query splitting (get_splits) requires num_splits > 1 because splitting produces boundaries between at least two regions; asking for 1 (or fewer, or negative) splits is meaningless, so SplitNotPossibleError (a QuerySplitterError) is raised before any scatter-query work.

Solutions

  1. Ensure num_splits >= 2 before calling get_splits (e.g. max(2, desired_splits)).
  2. Skip splitting entirely when only one split is needed — query without a split.
  3. Fix the computation producing num_splits (check for zero remaining jobs/workers) and clamp it.
  4. Catch SplitNotPossibleError and fall back to an unsplit query.

Example fix

// before
splits = query_splitter.get_splits(client, query, num_splits)  # num_splits may be 1
// after
if num_splits > 1:
    splits = query_splitter.get_splits(client, query, num_splits)
else:
    splits = [query]
Defensive patterns

Strategy: validation

Validate before calling

if num_splits is None or num_splits <= 1:
    raise ValueError('num_splits must be >= 2 before calling get_splits')

Type guard

def can_split(num_splits):
    return isinstance(num_splits, int) and num_splits > 1

Try / catch

try:
    splits = query_splitter.get_splits(client, query, num_splits)
except SplitNotPossibleError:
    splits = [query]  # run unsplit

Prevention

When it happens

Trigger: Calling get_splits(client, query, num_splits) with num_splits <= 1 — e.g. passing num_splits=1, 0, or a computed value like int(total_workers / num_jobs) that evaluates to 1 or 0 when few workers/jobs are configured.

Common situations: Dynamic work rebalancing computing splits from remaining work counts that reach 0; configured parallelism of 1; integer division rounding down to 1 or 0 for small inputs.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/9438330e8f6f85bb. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/io/gcp/datastore/v1new/query_splitter.py:72

  gather random split points for a query.

  Note: This implementation is derived from the java query splitter in
  https://github.com/GoogleCloudPlatform/google-cloud-datastore/blob/master/java/datastore/src/main/java/com/google/datastore/v1/client/QuerySplitterImpl.java

  Args:
    client: the datastore client.
    query: the query to split.
    num_splits: the desired number of splits.

  Returns:
    A list of split queries, of a max length of `num_splits`

  Raises:
    QuerySplitterError: if split could not be performed owing to query or split
      parameters.
  """
  if num_splits <= 1:
    raise SplitNotPossibleError('num_splits must be > 1, got: %d' % num_splits)
  validate_split(query)

  splits = []
  client_scatter_keys = _get_scatter_keys(client, query, num_splits)
  last_client_key = None
  for next_client_key in _get_split_key(client_scatter_keys, num_splits):
    splits.append(_create_split(last_client_key, next_client_key, query))
    last_client_key = next_client_key

  splits.append(_create_split(last_client_key, None, query))
  return splits


def validate_split(query):
  """
  Verifies that the given query can be properly scattered.

  Note that equality and ancestor filters are allowed, however they may result

View on GitHub (pinned to 12126d8942)