apache/beam · error · ValueError

micros and subseconds are mutually exclusive, got micros=

Error message

micros and subseconds are mutually exclusive, got micros=%s, subseconds=%s.

What it means

Timestamp.__init__ forbids supplying both `micros` and a truthy `subseconds` because they are two representations of the same quantity and would be ambiguous. Supplying both raises a ValueError telling you which values conflicted.

Solutions

  1. Remove the subseconds argument and keep only micros
  2. Or remove micros and express the value entirely as subseconds
  3. Note subseconds=0 with micros is permitted, so only nonzero subseconds conflict

Example fix

// before
Timestamp(micros=100, subseconds=50)
// after
Timestamp(micros=100)  # or Timestamp(subseconds=50, precision=...)
Defensive patterns

Strategy: validation

Validate before calling

if micros is not None and subseconds:
    raise ValueError('pass either micros or subseconds, not both')

Try / catch

try:
    ts = Timestamp(**kwargs)
except ValueError as e:
    if 'mutually exclusive' in str(e):
        kwargs.pop('subseconds', None)
        ts = Timestamp(**kwargs)

Prevention

When it happens

Trigger: Timestamp(micros=100, subseconds=50) — micros is not None and subseconds is truthy; passing subseconds=0 with micros is allowed (0 is falsy).

Common situations: Refactor that switched from subseconds to micros but left the old argument in place; generic wrapper code that forwards all kwargs; copy-paste in tests.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/utils/timestamp.py:101

      raise TypeError(
          'Cannot interpret %s %s as seconds.' % (seconds, type(seconds)))
    if not isinstance(subseconds, (int, float)):
      raise TypeError(
          'Cannot interpret %s %s as subseconds.' %
          (subseconds, type(subseconds)))
    if not isinstance(precision, int):
      raise TypeError(
          'Cannot interpret %s %s as precision.' % (precision, type(precision)))
    if not 0 <= precision <= Timestamp.NANOS_PRECISION:
      raise ValueError(
          'Timestamp precision must be between 0 and %d (inclusive), '
          'but was %d.' % (Timestamp.NANOS_PRECISION, precision))
    if micros is not None:
      if not isinstance(micros, (int, float)):
        raise TypeError(
            'Cannot interpret %s %s as micros.' % (micros, type(micros)))
      if subseconds:
        raise ValueError(
            'micros and subseconds are mutually exclusive, got micros=%s, '
            'subseconds=%s.' % (micros, subseconds))
      if precision != Timestamp.MICROS_PRECISION:
        raise ValueError(
            'micros implies microsecond precision (6) but precision was %d; '
            'use subseconds instead.' % precision)
      subseconds = micros
    self._precision = precision
    total = int(seconds * _POW_10[precision]) + int(subseconds)
    self._seconds, self._subseconds = divmod(total, _POW_10[precision])

  def _total(self, precision: int) -> int:
    """Returns the total time since the epoch in units of 10**-precision
    seconds.

    ``precision`` must be greater than or equal to this timestamp's
    precision, so that scaling up is always lossless.
    """

View on GitHub (pinned to 12126d8942)