{"record":{"id":"75f7905565f98e77","repo":"apache/beam","slug":"could-not-parse-rfc-3339-string-due-to-error","errorCode":null,"errorMessage":"Could not parse RFC 3339 string '{}' due to error: '{}'.","messagePattern":"Could not parse RFC 3339 string '(.+?)' due to error: '(.+?)'\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/timestamp.py","lineNumber":191,"sourceCode":"\n  @classmethod\n  def from_rfc3339(cls, rfc3339: str) -> 'Timestamp':\n    \"\"\"Create a ``Timestamp`` instance from an RFC 3339 compliant string.\n\n    Fractional seconds up to microseconds produce a microsecond-precision\n    Timestamp; a longer fraction (up to nanoseconds) produces a Timestamp\n    whose precision matches the number of fractional digits.\n\n    .. note::\n      All timezones are implicitly converted to UTC.\n\n    Args:\n      rfc3339: String in RFC 3339 form.\n    \"\"\"\n    try:\n      dt = dateutil.parser.isoparse(rfc3339).astimezone(pytz.UTC)\n    except ValueError as e:\n      raise ValueError(\n          \"Could not parse RFC 3339 string '{}' due to error: '{}'.\".format(\n              rfc3339, e))\n    timestamp = cls.from_utc_datetime(dt)\n    # dateutil silently truncates fractional seconds to microseconds; parse\n    # any sub-microsecond digits ourselves to avoid losing precision.\n    fraction = re.search(r'[0-9]{2}[.,]([0-9]{7,})', rfc3339)\n    if fraction:\n      digits = fraction.group(1)\n      if len(digits) > cls.NANOS_PRECISION:\n        raise ValueError(\n            \"Could not parse RFC 3339 string '%s': fractional seconds \"\n            'beyond nanosecond precision are not supported.' % rfc3339)\n      precision = len(digits)\n      sub_micro = int(digits[cls.MICROS_PRECISION:])\n      return Timestamp(\n          timestamp.seconds(),\n          timestamp.subseconds() * _POW_10[precision - cls.MICROS_PRECISION] +\n          sub_micro,","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/timestamp.py#L173-L209","documentation":"from_rfc3339() parses the string with dateutil.parser.isoparse(); if that raises ValueError, it is re-raised with a message including both the input string and the underlying parse error. This means the input was not a valid RFC 3339 / ISO-8601 timestamp.","triggerScenarios":"Timestamp.from_rfc3339('2024-13-45T99:00:00Z'); 'Jan 1 2024'; empty string; truncated strings like '2024-01-01T10:'; timezone-less strings that isoparse rejects in strict contexts.","commonSituations":"Free-form user input into an API field; log-parsing pipelines fed non-RFC3339 formats; typos like double T or missing seconds parts; locale-formatted dates.","solutions":["Validate/fix the input to RFC 3339 form, e.g. '2024-01-01T00:00:00Z'","Read the wrapped inner error (the trailing 'error' in the message) to pinpoint the malformed part","Pre-parse with dateutil.parser.parse for lenient formats, then convert to an aware UTC datetime and use Timestamp.of"],"exampleFix":"// before\nts = Timestamp.from_rfc3339(user_input)  # '01/02/2024 3pm'\n// after\ndt = dateutil.parser.parse(user_input)\nts = Timestamp.of(dt.astimezone(pytz.utc))","handlingStrategy":"try-catch","validationCode":"RFC3339_RE = re.compile(r'^\\d{4}-\\d{2}-\\d{2}[Tt ]\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?([Zz]|[+-]\\d{2}:?\\d{2})$')\nif not RFC3339_RE.match(s):\n    raise ValueError(f'not RFC 3339: {s!r}')","typeGuard":null,"tryCatchPattern":"try:\n    ts = Timestamp.from_rfc3339(s)\nexcept ValueError as e:\n    log.error('bad timestamp %r: %s', s, e)\n    ts = None  # or dead-letter the record","preventionTips":["Validate input format before parsing; surface the inner error message","Fix upstream producers to emit RFC 3339 with an explicit offset","Keep a dead-letter path for unparseable timestamps in pipelines"],"tags":["python","value-error","timestamp","rfc3339","parsing"],"backgroundTag":"invalid-date-format","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"}