{"record":{"id":"6fa1304953e2b4c2","repo":"apache/beam","slug":"the-remainder-of-r-modulo-r-has-sub-microsecond-precision","errorCode":null,"errorMessage":"The remainder of %r modulo %r has sub-microsecond precision, which Duration cannot represent. Truncate this timestamp with to_precision(6, allow_lossy_conversion=True) first.","messagePattern":"The remainder of %r modulo %r has sub-microsecond precision, which Duration cannot represent\\. Truncate this timestamp with to_precision\\(6, allow_lossy_conversion=True\\) first\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/timestamp.py","lineNumber":470,"sourceCode":"        raise ValueError(\n            'The difference of %r and %r has sub-microsecond precision, '\n            'which Duration cannot represent. Truncate the operands with '\n            'to_precision(6, allow_lossy_conversion=True) first.' %\n            (self, other))\n      return Duration(micros=diff_nanos // 1000)\n    other = Duration.of(other)\n    precision = max(self._precision, Timestamp.MICROS_PRECISION)\n    return Timestamp(\n        subseconds=self._total(precision) -\n        other.micros * _POW_10[precision - Timestamp.MICROS_PRECISION],\n        precision=precision)\n\n  def __mod__(self, other: DurationTypes) -> 'Duration':\n    other = Duration.of(other)\n    remainder_nanos = self._total(Timestamp.NANOS_PRECISION) % (\n        other.micros * 1000)\n    if remainder_nanos % 1000 != 0:\n      raise ValueError(\n          'The remainder of %r modulo %r has sub-microsecond precision, '\n          'which Duration cannot represent. Truncate this timestamp with '\n          'to_precision(6, allow_lossy_conversion=True) first.' % (self, other))\n    return Duration(micros=remainder_nanos // 1000)\n\n\nMIN_TIMESTAMP = Timestamp(\n    micros=int(common_urns.constants.MIN_TIMESTAMP_MILLIS.constant) * 1000)\nMAX_TIMESTAMP = Timestamp(\n    micros=int(common_urns.constants.MAX_TIMESTAMP_MILLIS.constant) * 1000)\n\n\nclass Duration(object):\n  \"\"\"Represents a second duration with microsecond granularity.\n\n  Can be treated in common arithmetic operations as a numeric type.\n\n  Internally stores a time interval as an int of microseconds. This strategy","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/timestamp.py#L452-L488","documentation":"Timestamp.__mod__ computes the timestamp modulo a Duration at nanosecond resolution and returns a Duration in microseconds. If the remainder has sub-microsecond digits it cannot be represented as a Duration, so a ValueError is raised telling you to truncate the timestamp first.","triggerScenarios":"Evaluating ts % duration (or ts % Duration.of(...)) where ts has nanosecond precision and the nanosecond remainder mod (duration.micros*1000) is not a multiple of 1000.","commonSituations":"Windowing/field-masking logic like ts % window_duration on high-precision timestamps; rate limiting or bucketing arithmetic ported from microsecond-precision data to nanosecond-precision data.","solutions":["Truncate the timestamp before the modulo: ts.to_precision(6, allow_lossy_conversion=True) % duration.","Compute the remainder with `.nanos` manually and decide how to handle sub-microsecond digits.","Ensure input timestamps are constructed/normalized to microsecond precision at ingest.","Catch ValueError and re-raise with context about the specific timestamp/duration pair."],"exampleFix":"// before\noffset = ts % Duration(seconds=30)\n// after\noffset = ts.to_precision(6, allow_lossy_conversion=True) % Duration(seconds=30)","handlingStrategy":"try-catch","validationCode":"def safe_mod(ts, dur):\n    r = ts.nanos % (dur.micros * 1000)\n    if r % 1000:\n        raise ValueError('sub-microsecond remainder')\n    return Duration(micros=r // 1000)","typeGuard":null,"tryCatchPattern":"try:\n    offset = ts % window\nexcept ValueError:\n    offset = ts.to_precision(6, allow_lossy_conversion=True) % window","preventionTips":["Normalize timestamps to microsecond precision before modulo/window math.","Use `.nanos` arithmetic if sub-microsecond remainders matter to your logic.","Document the truncation policy for windowing code."],"tags":["python","apache-beam","timestamp","duration","precision-loss"],"backgroundTag":"precision-loss","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}