apache/beam · error · ValueError

number value must be within [0, %s)

Error message

number value must be within [0, %s)

What it means

_ObjectIdHelper.int_to_id converts a 96-bit integer into a 12-byte MongoDB ObjectId. Because an ObjectId holds only 12 bytes, values must satisfy 0 <= number < 2**96; anything outside raises ValueError('number value must be within [0, 2**96)').

Source

Thrown at sdks/python/apache_beam/io/mongodbio.py:622

    # converts object id binary to integer
    # id object is bytes type with size of 12
    ints = struct.unpack(">III", _id.binary)
    return (ints[0] << 64) + (ints[1] << 32) + ints[2]

  @classmethod
  def int_to_id(cls, number):
    """
    Args:
      number(int): The integer value to be used to convert to ObjectId.

    Returns: The ObjectId that has the 12 bytes binary converted from the
      integer value.
    """
    # converts integer value to object id. Int value should be less than
    # (2 ^ 96) so it can be convert to 12 bytes required by object id.
    if number < 0 or number >= (1 << 96):
      raise ValueError("number value must be within [0, %s)" % (1 << 96))
    ints = [
        (number & 0xFFFFFFFF0000000000000000) >> 64,
        (number & 0x00000000FFFFFFFF00000000) >> 32,
        number & 0x0000000000000000FFFFFFFF,
    ]

    number_bytes = struct.pack(">III", *ints)
    return ObjectId(number_bytes)

  @classmethod
  def increment_id(
      cls,
      _id: ObjectId,
      inc: int,
  ) -> ObjectId:
    """
    Increment object_id binary value by inc value and return new object id.

View on GitHub (pinned to 12126d8942)

Solutions

  1. Mask the value into range before converting: number % (1 << 96).
  2. Clamp negative values to 0 and validate 0 <= number < 2**96 before calling.
  3. Derive the int from a real 12-byte ObjectId via id_to_int instead of an arbitrary wide integer.
  4. For very large counters, switch to lexicographic string positions rather than int-to-ObjectId conversion.

Example fix

// before
oid = _ObjectIdHelper.int_to_id(hash(value))
// after
n = hash(value) % (1 << 96)
oid = _ObjectIdHelper.int_to_id(n)
Defensive patterns

Strategy: validation

Validate before calling

if not (0 <= number < (1 << 96)):
    raise ValueError('number out of ObjectId range')

Type guard

def fits_object_id(n: int) -> bool:
    return isinstance(n, int) and 0 <= n < (1 << 96)

Try / catch

try:
    oid = _ObjectIdHelper.int_to_id(number)
except ValueError:
    oid = _ObjectIdHelper.int_to_id(number % (1 << 96))

Prevention

When it happens

Trigger: Calling _ObjectIdHelper.int_to_id with a negative number, or a number >= 79228162514264337593543950335 (2**96) — e.g. after repeatedly incrementing an id, or converting a random int without masking to 96 bits.

Common situations: Generating synthetic _id values by integer arithmetic that overflows 96 bits; computing ids from hashes/uuids wider than 96 bits; incrementing beyond the max id during pagination loops.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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