apache/beam · error · ValueError

Timestamp precision must be between 0 and %d (inclusive), bu

Error message

Timestamp precision must be between 0 and %d (inclusive), but was %d.

What it means

ParameterizedTimestamp validates its precision argument: after int coercion it must be between 0 and Timestamp.NANOS_PRECISION (9, nanosecond precision). Values outside that range raise ValueError. Precision denotes the number of subsecond digits the timestamp encodes.

Source

Thrown at sdks/python/apache_beam/typehints/schemas.py:1037

  always in ``[0, 10**precision)``.
  ``subseconds`` is an INT16 field for precision < 5 and an INT32
  field otherwise.

  Note: Timestamp originating from Python to xlang still defaults to
  MicrosInstant for backwards compatibility. To override the mapping of
  Timestamp to this logical type, re-register using
  :func:`~LogicalType.register_logical_type(ParameterizedTimestamp)`.
  """
  def __init__(self, precision: Optional[int] = None) -> None:
    if precision is None:
      # A timestamp:v1 proto without its precision argument is malformed;
      # decoding at a guessed precision would silently misscale subseconds.
      raise ValueError(
          'beam:logical_type:timestamp:v1 requires a precision argument.')
    # The argument arrives as np.int32 when decoded from a schema proto.
    precision = int(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))
    self._precision = precision

  @classmethod
  def urn(cls):
    return common_urns.timestamp.urn

  def representation_type(self) -> type:  # type: ignore[override]
    # Unlike other logical types, the representation depends on the
    # argument, so this is an instance method rather than a classmethod.
    if self._precision < _TIMESTAMP_SHORT_PRECISION_LIMIT:
      return ParameterizedTimestampShortRepresentation
    return ParameterizedTimestampRepresentation

  @classmethod
  def language_type(cls):
    return Timestamp

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use precision as a digit count between 0 (seconds) and 9 (nanoseconds): seconds=0, millis=3, micros=6, nanos=9.
  2. Clamp or validate the precision before constructing: 0 <= int(precision) <= 9.
  3. Convert a unit enum to a digit count before passing it in.

Example fix

// before
lt = ParameterizedTimestamp(precision=1_000_000_000)  # out of range

// after
lt = ParameterizedTimestamp(precision=9)  # nanosecond precision
Defensive patterns

Strategy: validation

Validate before calling

def valid_precision(p):
    return isinstance(p, (int, float)) and 0 <= int(p) <= 9

Type guard

def is_precision(p) -> bool:
    return isinstance(p, int) and not isinstance(p, bool) and 0 <= p <= 9

Try / catch

try:
    lt = ParameterizedTimestamp(precision=p)
except ValueError:
    p = min(max(int(p), 0), 9)
    lt = ParameterizedTimestamp(precision=p)

Prevention

When it happens

Trigger: Calling ParameterizedTimestamp(precision=-1), precision=10, precision=100, or any non-None value that is not an integer in [0, 9]; passing a string/float that coerces out of range.

Common situations: Confusing precision (digit count, max 9) with a time unit enum or nanosecond magnitude (e.g. passing 1_000_000_000); off-by-one misuse thinking milliseconds are precision 3+something; passing fractional precision values.

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/6041e9af5e6876fe. Report an issue: GitHub.