Skip to content

Error in timezone handling GHC Runner #506

Closed

Description

@justb4

Describe the bug
The APScheduler suddenly gives errors.

To Reproduce
Steps to reproduce the behavior, e.g.:

  1. add a Resource, e.g. WMS
  2. Wait for execution
  3. See error (see below)

Expected Behavior
No error.

Screenshots or Logfiles

2026-06-26 18:11:28,225 - apscheduler.executors.default - ERROR - Job "run_job (trigger: interval[0:30:00], next run at: 2026-06-26 18:41:28 CEST)" raised an exception
Traceback (most recent call last):
  File "/GeoHealthCheck/lib/python3.12/site-packages/apscheduler/executors/base.py", line 131, in run_job
    retval = job.func(*job.args, **job.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/GeoHealthCheck/GeoHealthCheck/scheduler.py", line 119, in run_job
    if not lock.obtain(uuid, frequency):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/GeoHealthCheck/GeoHealthCheck/models.py", line 693, in obtain
    if not self.has_expired():
           ^^^^^^^^^^^^^^^^^^
  File "/GeoHealthCheck/GeoHealthCheck/models.py", line 690, in has_expired
    return now > self.end_time
           ^^^^^^^^^^^^^^^^^^^
TypeError: can't compare offset-naive and offset-aware datetimes
2026-06-26 18:11:28,228 - __main__ - ERROR - error_listener: EVENT_JOB_MISSED - <self.__class__.__name__ (code=8192)>

Context (please complete the following information):

  • OS: any
  • Browser NA
  • Browser Version NA
  • Python Version 3.12
  • GeoHealthCheck Version master on June 26, 2026

If running with Docker:

  • Docker installed version
  • GeoHealthCheck Docker Image version : latest

**Analysis
I suspect this happens since tzlocal upgrade to latest version related to APScheduler. The previous was tzlocal<3.0
Now:

 tzdata                         2025c        hc9c84f9_1          conda-forge
  tzlocal                        5.4.3        pypi_0              pypi 

See YelpArchive/elastalert#2968

Plus seems to happen only on existing databases, i.e. jobs stored.
Suspect difference/mismatch between: "Offset-naive and Offset-aware datetimes".
Newly added jobs work ok, like this local instance:

2026-06-26 19:21:18,133 - apscheduler.executors.default - INFO - Running job "run_job (trigger: interval[0:10:00], next run at: 2026-06-26 19:31:18 CEST)" (scheduled at 2026-06-26 19:21:18.127902+02:00)
2026-06-26 19:21:18,139 - scheduler - INFO - 1 No Lock at all: obtain new
2026-06-26 19:21:18,155 - GeoHealthCheck.probe - INFO - Requesting: GET url=https://service.pdok.nl/kadaster/adressen/wms/v1_0
2026-06-26 19:21:18,162 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): service.pdok.nl:443
2026-06-26 19:21:18,257 - urllib3.connectionpool - DEBUG - https://service.pdok.nl:443 "GET /kadaster/adressen/wms/v1_0?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities HTTP/1.1" 200 9391
2026-06-26 19:21:18,257 - GeoHealthCheck.probe - INFO - response: status=200
2026-06-26 19:21:18,258 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.HttpStatusNoError result=True
2026-06-26 19:21:18,258 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.XmlParse result=True
2026-06-26 19:21:18,258 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.NotContainsOwsException result=True
2026-06-26 19:21:18,258 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.ContainsStrings result=True
2026-06-26 19:21:18,258 - GeoHealthCheck.probe - INFO - Result: success=True msg=OK response_time=0.103404
2026-06-26 19:21:18,262 - scheduler - INFO - 1 run_resource OK

Activity

  1. added 4 commits that reference this issue on Jun 27, 2026
  2. justb4 commented on Jun 27, 2026

    @justb4
    MemberAuthor

    In the end the fix was simple, always set a timezone for the DB attribute (which is UTC anyway, but without TZ info as set by SQLAlchemy):

    end_time = self.end_time.replace(tzinfo=timezone.utc)
            return now > end_time
    

    Now APScheduler works again agains existing data! Has to do with ResourceLock which is not always needed. For example:

    2026-06-27 17:57:14,474 - __main__ - INFO - 646 Lock present: try obtaining..
    2026-06-27 17:57:14,474 - __main__ - INFO - 646 Lock obtained, delete and renew
    2026-06-27 17:57:14,477 - __main__ - INFO - 646 Lock deleted, add new
    2026-06-27 17:57:14,484 - __main__ - INFO - 646 Lock Add OK
    2026-06-27 17:57:14,498 - GeoHealthCheck.probe - INFO - Requesting: GET url=https://opendata.lgln.niedersachsen.de/doorman/noauth/dop_wms
    2026-06-27 17:57:14,749 - GeoHealthCheck.probe - INFO - response: status=200
    2026-06-27 17:57:14,750 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.HttpStatusNoError result=True
    2026-06-27 17:57:14,751 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.XmlParse result=True
    2026-06-27 17:57:14,751 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.NotContainsOwsException result=True
    2026-06-27 17:57:14,752 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.ContainsStrings result=True
    2026-06-27 17:57:14,752 - GeoHealthCheck.probe - INFO - Result: success=True msg=OK response_time=0.252429
    2026-06-27 17:57:14,754 - GeoHealthCheck.probe - INFO - Requesting: GET url=https://opendata.lgln.niedersachsen.de/doorman/noauth/dop_wms
    2026-06-27 17:57:15,342 - GeoHealthCheck.probe - INFO - response: status=200
    2026-06-27 17:57:15,342 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.HttpStatusNoError result=True
    2026-06-27 17:57:15,393 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.NotContainsOwsException result=True
    2026-06-27 17:57:15,394 - GeoHealthCheck.probe - INFO - Check: fun=GeoHealthCheck.plugins.check.checks.HttpHasImageContentType result=True
    2026-06-27 17:57:15,394 - GeoHealthCheck.probe - INFO - Result: success=True msg=OK response_time=0.587797
    2026-06-27 17:57:15,405 - __main__ - INFO - 646 run_resource OK
    202
    
  3. reopened this on Sep 9, 2026
  4. justb4 commented on Sep 9, 2026

    @justb4
    MemberAuthor

    Re-opened as a similar error popped up in 0.10.0 release. This error stops the Runner during flush of old Runs outside retention window:

    2026-08-22 17:47:09,440 - apscheduler.executors.default - ERROR - Job "flush_runs (trigger: interval[2:30:00], next run at: 2026-08-22 22:17:00 CEST)" raised an exception
    Traceback (most recent call last):
      File "/app/.pixi/envs/prod/lib/python3.12/site-packages/apscheduler/executors/base.py", line 131, in run_job
        retval = job.func(*job.args, **job.kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/GeoHealthCheck/models.py", line 61, in flush_runs
        days_old = (datetime.now(timezone.utc) - run.checked_datetime).days
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
    TypeError: can't subtract offset-naive and offset-aware datetimes
    END run-runner.sh
    

    Strange is that this only happens on a single (customer) instance. E.g. not on demo-site and with other (geoqos) customers who all run 0.10.0. Could be due to "old" dates in DB (?).

  5. justb4 commented on Sep 19, 2026

    @justb4
    MemberAuthor

    It actually happens in any instance, so fixing with test as well, check should become:
    days_old = (datetime.now(timezone.utc) - run.checked_datetime.replace(tzinfo=timezone.utc)).days

  6. added 2 commits that reference this issue on Sep 19, 2026
  7. self-assigned this
    on Sep 20, 2026
  8. added theissue type on Sep 20, 2026
  9. added this to the Version 0.10.1 milestone on Sep 20, 2026
  10. justb4 commented on Sep 20, 2026

    @justb4
    MemberAuthor

    Fixed through #521 , closing.

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

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions