{"record":{"id":"115e6fb97f694d8b","repo":"apache/beam","slug":"expected-apache-beam-utils-timestamp-timestamp-or-google","errorCode":null,"errorMessage":"Expected apache_beam.utils.timestamp.Timestamp, or google.protobuf.timestamp_pb2.Timestamp. Got %s","messagePattern":"Expected apache_beam\\.utils\\.timestamp\\.Timestamp, or google\\.protobuf\\.timestamp_pb2\\.Timestamp\\. Got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/portability/abstract_job_service.py","lineNumber":57,"sourceCode":"from apache_beam.portability.api import beam_job_api_pb2\nfrom apache_beam.portability.api import beam_job_api_pb2_grpc\nfrom apache_beam.portability.api import beam_runner_api_pb2\nfrom apache_beam.portability.api import endpoints_pb2\nfrom apache_beam.runners.portability import artifact_service\nfrom apache_beam.utils.timestamp import Timestamp\n\n_LOGGER = logging.getLogger(__name__)\n\nStateEvent = tuple[int, Union[timestamp_pb2.Timestamp, Timestamp]]\n\n\ndef make_state_event(state, timestamp):\n  if isinstance(timestamp, Timestamp):\n    proto_timestamp = timestamp.to_proto()\n  elif isinstance(timestamp, timestamp_pb2.Timestamp):\n    proto_timestamp = timestamp\n  else:\n    raise ValueError(\n        \"Expected apache_beam.utils.timestamp.Timestamp, \"\n        \"or google.protobuf.timestamp_pb2.Timestamp. \"\n        \"Got %s\" % type(timestamp))\n\n  return beam_job_api_pb2.JobStateEvent(state=state, timestamp=proto_timestamp)\n\n\nclass AbstractJobServiceServicer(beam_job_api_pb2_grpc.JobServiceServicer):\n  \"\"\"Manages one or more pipelines, possibly concurrently.\n  Experimental: No backward compatibility guaranteed.\n  Servicer for the Beam Job API.\n  \"\"\"\n  def __init__(self):\n    self._jobs: dict[str, AbstractBeamJob] = {}\n\n  def create_beam_job(\n      self,\n      preparation_id,  # stype: str","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/portability/abstract_job_service.py#L39-L75","documentation":"make_state_event converts a job-state timestamp into a proto Timestamp for a beam_job_api_pb2.JobStateEvent. The service raises ValueError when the timestamp is neither an apache_beam.utils.timestamp.Timestamp nor a google.protobuf.timestamp_pb2.Timestamp, because no other type can be written to the proto field.","triggerScenarios":"Calling make_state_event (directly, or indirectly via GetState/GetStateStream/GetMessageStream backed by a custom AbstractBeamJob whose get_state_stream()/get_message_stream() yield timestamps) with any other type, e.g. datetime.datetime, int/float epoch seconds, or a string.","commonSituations":"Implementing a custom Beam job class that yields datetime objects or epoch numbers instead of the two supported Timestamp types; assuming datetimes are auto-converted.","solutions":["Coerce the value before it reaches the service: apache_beam.utils.timestamp.Timestamp.of(value) for epoch/seconds/datetime inputs.","For datetime objects, convert explicitly with timestamp_pb2.Timestamp().FromDatetime(dt).","Fix the custom job class so get_state_stream()/get_message_stream() yield Timestamp or timestamp_pb2.Timestamp."],"exampleFix":"// before\nyield state, datetime.datetime.utcnow()\n// after\nfrom apache_beam.utils.timestamp import Timestamp\nyield state, Timestamp.now()","handlingStrategy":"validation","validationCode":"from apache_beam.utils.timestamp import Timestamp\nfrom google.protobuf import timestamp_pb2\n\ndef valid_job_timestamp(ts):\n    return isinstance(ts, (Timestamp, timestamp_pb2.Timestamp))\n\nassert valid_job_timestamp(my_ts), \"convert with Timestamp.of(ts) first\"","typeGuard":"def is_beam_timestamp(ts) -> bool:\n    return isinstance(ts, (Timestamp, timestamp_pb2.Timestamp))","tryCatchPattern":"try:\n    event = make_state_event(state, ts)\nexcept (ValueError, TypeError):\n    event = make_state_event(state, Timestamp.of(ts))  # coerce datetime/epoch","preventionTips":["Always yield Timestamp or timestamp_pb2.Timestamp from custom job get_state_stream/get_message_stream.","Coerce datetimes/epoch numbers at the boundary with Timestamp.of().","Assert the timestamp type in your job class before yielding."],"tags":["python","type-mismatch","apache-beam","grpc-job-service"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}