{"record":{"id":"92c102e1c30e85a0","repo":"apache/beam","slug":"cannot-interpret-s-as-duration","errorCode":null,"errorMessage":"Cannot interpret %s as Duration.","messagePattern":"Cannot interpret (.+?) as Duration\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/timestamp.py","lineNumber":513,"sourceCode":"      seconds: Union[int, float] = 0,\n      micros: Union[int, float] = 0) -> None:\n    self.micros = int(seconds * 1000000) + int(micros)\n\n  @staticmethod\n  def of(seconds: DurationTypes) -> 'Duration':\n    \"\"\"Return the Duration for the given number of seconds since Unix epoch.\n\n    If the input is already a Duration, the input itself will be returned.\n\n    Args:\n      seconds: Number of seconds as int, float or Duration.\n\n    Returns:\n      Corresponding Duration object.\n    \"\"\"\n\n    if isinstance(seconds, Timestamp):\n      raise TypeError('Cannot interpret %s as Duration.' % seconds)\n    if isinstance(seconds, Duration):\n      return seconds\n    return Duration(seconds)\n\n  def to_proto(self) -> duration_pb2.Duration:\n    \"\"\"Returns the `google.protobuf.duration_pb2` representation.\"\"\"\n    secs = self.micros // 1000000\n    nanos = (self.micros % 1000000) * 1000\n    return duration_pb2.Duration(seconds=secs, nanos=nanos)\n\n  @staticmethod\n  def from_proto(duration_proto: duration_pb2.Duration) -> 'Duration':\n    \"\"\"Creates a Duration from a `google.protobuf.duration_pb2`.\n\n    Note that the google has a sub-second resolution of nanoseconds whereas this\n    class has a resolution of microsends. This class will truncate the\n    nanosecond resolution down to the microsecond.\n    \"\"\"","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/timestamp.py#L495-L531","documentation":"Duration.of() converts seconds/Timestamp-like inputs into a Duration, but a Timestamp represents an instant, not a span of time, so it is rejected with a TypeError rather than being silently misinterpreted as seconds.","triggerScenarios":"Calling Duration.of(ts) or passing a Timestamp where a duration-like value is expected, e.g. Duration.of(seconds=some_timestamp), or __sub__/__mod__ paths that call Duration.of on a Timestamp operand.","commonSituations":"Confusing an event timestamp with a duration in pipeline code; passing the wrong variable (a Timestamp where a Duration or numeric seconds was intended); porting code between Timestamp and Duration APIs.","solutions":["Subtract two Timestamps to get a Duration: Duration.of(ts_end - ts_start).","Pass a numeric seconds value or a Duration instance instead of a Timestamp.","Check variable types before calling; a type guard like isinstance(x, Timestamp) can route to the right conversion.","If you truly want the epoch-relative span, extract ts.micros or ts.seconds and construct Duration(micros=...) explicitly."],"exampleFix":"// before\nDuration.of(ts)  # TypeError\n// after\nDuration(micros=ts.micros)  # explicit epoch-relative duration\n# or, for a span:\nDuration.of(ts_end - ts_start)","handlingStrategy":"type-guard","validationCode":"if isinstance(value, Timestamp):\n    raise TypeError('got Timestamp where Duration expected')\nduration = Duration.of(value)","typeGuard":"def is_duration_like(x):\n    return isinstance(x, (Duration, int, float)) and not isinstance(x, Timestamp)","tryCatchPattern":"try:\n    duration = Duration.of(value)\nexcept TypeError:\n    duration = Duration(micros=value.micros)  # or fix the caller","preventionTips":["Distinguish instants (Timestamp) from spans (Duration) in variable naming.","Convert between them explicitly (ts2 - ts1, Duration(micros=...)).","Add isinstance assertions when accepting duration-like parameters."],"tags":["python","apache-beam","duration","type-error"],"backgroundTag":"type-mismatch","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"}