Skip to content

Function Scheduler failing due to incorrect timestamp format #255

Closed

Description

@BennetVellaExient
File "/layers/google.python.pip/pip/lib/python3.12/site-packages/firebase_functions/scheduler_fn.py", line 102, in on_schedule_wrapped
    schedule_time = _dt.datetime.strptime(
                    ^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.runtime/python/lib/python3.12/_strptime.py", line 653, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.runtime/python/lib/python3.12/_strptime.py", line 432, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '2025-10-17T16:50:00.510855-07:00' does not match format '%Y-%m-%dT%H:%M:%S%z'"

This started happening over the weekend with no changes / alterations to our workers. From the internal logic it appears to be sourced at:

    def on_schedule_decorator(func: _C):

        @_functools.wraps(func)
        def on_schedule_wrapped(request: _Request) -> _Response:
            schedule_time: _dt.datetime
            schedule_time_str = request.headers.get(
                "X-CloudScheduler-ScheduleTime")
            if schedule_time_str is None:
                schedule_time = _dt.datetime.utcnow()
            else:
                schedule_time = _dt.datetime.strptime(
                    schedule_time_str,
                    "%Y-%m-%dT%H:%M:%S%z",
                )

So I'm suspecting that the following request.headers.get("X-CloudScheduler-ScheduleTime") has changed? Upgrading the sdk version is likely to be a major endeavour, what's the simplest solution here?

Activity

  1. BennetVellaExient commented on Oct 20, 2025

    @BennetVellaExient
    Author
    def on_schedule_wrapped(request: _Request) -> _Response:
        schedule_time_str = request.headers.get("X-CloudScheduler-ScheduleTime")
    
        if schedule_time_str is None:
            schedule_time = _dt.utcnow()
        else:
            try:
                # Supports the expected RFC 3339 format and ISO 8601 as well
                schedule_time = dateutil_parser.isoparse(schedule_time_str)
            except ValueError as e:
                print(f"Failed to parse RFC 3339 timestamp: {e}")
                schedule_time = _dt.utcnow()

    Something like the above might be what we would want, since the incoming datetime still satisfies the documented definition, but the current implementation does not.

    Reference:
    https://cloud.google.com/scheduler/docs/reference/rpc/google.cloud.scheduler.v1#appenginehttptarget

  2. CorieW commented on Oct 20, 2025

    @CorieW
    Member

    Hi @BennetVellaExient! Thanks for raising this. It's been received and we will provide updates when available.

  3. BennetVellaExient commented on Oct 20, 2025

    @BennetVellaExient
    Author

    fix-cloudscheduler-scheduletime.patch

    Content:

    diff --git a/src/firebase_functions/scheduler_fn.py b/src/firebase_functions/scheduler_fn.py
    index 1979f67..8fee83d 100644
    --- a/src/firebase_functions/scheduler_fn.py
    +++ b/src/firebase_functions/scheduler_fn.py
    @@ -103,10 +103,16 @@ def on_schedule(**kwargs) -> _typing.Callable[[_C], _Response]:
                 if schedule_time_str is None:
                     schedule_time = _dt.datetime.utcnow()
                 else:
    -                schedule_time = _dt.datetime.strptime(
    -                    schedule_time_str,
    -                    "%Y-%m-%dT%H:%M:%S%z",
    -                )
    +                try:
    +                    # Robust RFC 3339 parsing
    +                    schedule_time = dateutil_parser.isoparse(schedule_time_str)
    +                except ValueError as e:
    +                    print(f"Failed to parse RFC 3339 timestamp: {e}")
    +                    schedule_time = _dt.utcnow()
    +                        schedule_time = _dt.datetime.strptime(
    +                            schedule_time_str,
    +                            "%Y-%m-%dT%H:%M:%S%z",
    +                        )
                 event = ScheduledEvent(
                     job_name=request.headers.get("X-CloudScheduler-JobName"),
                     schedule_time=schedule_time,
    

    Maybe this is of use.

  4. KoblerS commented on Nov 4, 2025

    @KoblerS

    any updates on this, since this is crucial for functions to work properly again

  5. BennetVellaExient commented on Nov 4, 2025

    @BennetVellaExient
    Author

    @KoblerS #256 was a proposed solution for this and @CorieW confirmed they're reviewing this today.

  6. KoblerS commented on Nov 4, 2025

    @KoblerS

    @KoblerS #256 was a proposed solution for this and @CorieW confirmed they're reviewing this today.

    thanks for the quick update! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions