apache/beam · error · TypeError
Cannot interpret as Duration.
Error message
Cannot interpret %s as Duration.
What it means
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.
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.
Example fix
// before Duration.of(ts) # TypeError // after Duration(micros=ts.micros) # explicit epoch-relative duration # or, for a span: Duration.of(ts_end - ts_start)
Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(value, Timestamp):
raise TypeError('got Timestamp where Duration expected')
duration = Duration.of(value) Type guard
def is_duration_like(x):
return isinstance(x, (Duration, int, float)) and not isinstance(x, Timestamp) Try / catch
try:
duration = Duration.of(value)
except TypeError:
duration = Duration(micros=value.micros) # or fix the caller Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- A cluster_identifier should be Optional[Union[str…
- Cannot convert from nanoseconds to microseconds because…
- Cannot get a type descriptor for
- CombineGlobally can be used only with combineFn objects…
- database_config must be VectorDatabaseWriteConfig, got
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/92c102e1c30e85a0.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/utils/timestamp.py:513
seconds: Union[int, float] = 0,
micros: Union[int, float] = 0) -> None:
self.micros = int(seconds * 1000000) + int(micros)
@staticmethod
def of(seconds: DurationTypes) -> 'Duration':
"""Return the Duration for the given number of seconds since Unix epoch.
If the input is already a Duration, the input itself will be returned.
Args:
seconds: Number of seconds as int, float or Duration.
Returns:
Corresponding Duration object.
"""
if isinstance(seconds, Timestamp):
raise TypeError('Cannot interpret %s as Duration.' % seconds)
if isinstance(seconds, Duration):
return seconds
return Duration(seconds)
def to_proto(self) -> duration_pb2.Duration:
"""Returns the `google.protobuf.duration_pb2` representation."""
secs = self.micros // 1000000
nanos = (self.micros % 1000000) * 1000
return duration_pb2.Duration(seconds=secs, nanos=nanos)
@staticmethod
def from_proto(duration_proto: duration_pb2.Duration) -> 'Duration':
"""Creates a Duration from a `google.protobuf.duration_pb2`.
Note that the google has a sub-second resolution of nanoseconds whereas this
class has a resolution of microsends. This class will truncate the
nanosecond resolution down to the microsecond.
"""View on GitHub (pinned to 12126d8942)