Skip to content

Intermittent "JWT token is not valid: Signature has expired" and PendingRollbackError after upgrade to FAB 5 #57065

Closed

Description

@ido177

Apache Airflow version

3.1.0

If "Other Airflow 2/3 version" selected, which one?

No response

What happened?

After upgrading to apache-airflow-providers-fab==3.0.0, which uses Flask AppBuilder 5, we started observing intermittent authentication-related crashes that make the Airflow Api Server unavailable.
The issue appears to be triggered by an expired or invalid JWT token, after which the Flask AppBuilder authentication manager fails to recover gracefully and raises a PendingRollbackError in SQLAlchemy.

2025-10-22T07:25:37.653971Z [error    ] JWT token is not valid: Signature has expired [airflow.api_fastapi.auth.managers.base_auth_manager] loc=base_auth_manager.py:107
INFO:     10.67.70.212:57914 - "GET /ui/config HTTP/1.1" 401 Unauthorized
2025-10-22T07:25:37.824145Z [error    ] Exception on /login/ [GET]     [airflow.providers.fab.www.app] loc=app.py:1744
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 2529, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 1821, in full_dispatch_request
    rv = self.preprocess_request()
         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 2313, in preprocess_request
    rv = self.ensure_sync(before_func)()
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/www/security_manager.py", line 57, in before_request
    g.user = get_auth_manager().get_user()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/auth_manager/fab_auth_manager.py", line 278, in get_user
    if current_user.is_anonymous and getattr(g, "user", None) is not None and not g.user.is_anonymous:
       ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/werkzeug/local.py", line 316, in __get__
    obj = instance._get_current_object()
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/werkzeug/local.py", line 520, in _get_current_object
    return get_name(local())  # type: ignore
                    ^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/flask_login/utils.py", line 25, in <lambda>
    current_user = LocalProxy(lambda: _get_user())
                                      ^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/flask_login/utils.py", line 370, in _get_user
    current_app.login_manager._load_user()
  File "/home/airflow/.local/lib/python3.12/site-packages/flask_login/login_manager.py", line 364, in _load_user
    user = self._user_callback(user_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/auth_manager/security_manager/override.py", line 1384, in load_user
    user = self.get_user_by_id(int(pk))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/auth_manager/security_manager/override.py", line 1390, in get_user_by_id
    return self.session.get(self.user_model, pk)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2853, in get
    return self._get_impl(
           ^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2975, in _get_impl
    return db_load_fn(
           ^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 530, in load_on_pk_identity
    session.execute(
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1717, in execute
    result = conn._execute_20(statement, params or {}, execution_options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20
    return meth(self, args_10style, kwargs_10style, execution_options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1808, in _execute_context
    conn = self._revalidate_connection()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 650, in _revalidate_connection
    self._invalid_transaction()
  File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 622, in _invalid_transaction
    raise exc.PendingRollbackError(
sqlalchemy.exc.PendingRollbackError: Can't reconnect until invalid transaction is rolled back. (Background on this error at: https://sqlalche.me/e/14/8s2b)

After this occurs, the Api Server becomes unresponsive until it’s restarted.

Image

What you think should happen instead?

The system should gracefully handle expired JWT tokens - e.g., invalidate the session, redirect the user to /login, and not leave SQLAlchemy sessions in a broken state.

How to reproduce

Unfortunately, this issue is intermittent - it’s not clear how to consistently reproduce it.
It tends to occur when:

  • The user session has expired and the UI tries to refresh(/ui/config or /login/),
  • Or when multiple requests hit the webserver simultaneously after an idle period.

Operating System

Debian

Versions of Apache Airflow Providers

apache-airflow==3.1.0
apache-airflow-providers-google==18.0.0
apache-airflow-providers-mysql==6.3.4
apache-airflow-providers-slack==9.3.0
apache-airflow-providers-vertica==4.1.2
apache-airflow-providers-apache-livy==4.4.3
apache-airflow-providers-ssh==4.1.4
apache-airflow-providers-common-sql==1.28.1
apache-airflow-providers-cncf-kubernetes==10.8.2
apache-airflow-providers-hashicorp==4.3.2
apache-airflow-providers-standard==1.9.0
apache-airflow-providers-postgres==6.3.0
apache-airflow-providers-apache-cassandra==3.8.2
apache-airflow-providers-fab==3.0.0
apache-airflow-providers-amazon==9.15.0

Deployment

Official Apache Airflow Helm Chart

Deployment details

airflow 3.1.0 in k8s deployed with official chart. We're also use pgbouncer for connection pooling

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. ido177 commented on Oct 22, 2025

    @ido177
    ContributorAuthor

    Looks similar to #39935

  2. eladkal commented on Oct 22, 2025

    @eladkal
    Contributor
  3. vincbeck commented on Oct 22, 2025

    @vincbeck
    Contributor

    Looking into it but I am unable to reproduce it. If some folks encounter the same issue and have "better" ways to reproduce it, I take it :)

  4. ido177 commented on Oct 23, 2025

    @ido177
    ContributorAuthor

    Hmm, how normal is it for a bad query to trigger a rollback, which blocks database access for the entire instance, causing a crash? It seems this issue highlights another problem. Perhaps we should somehow isolate connection pools from each other so that a problem at the authentication stage doesn't crash the entire production instance?

    Unfortunately, I don't know how to reproduce this issue, which is why I indicated it's intermittent.

  5. msenmurugan commented on Oct 24, 2025

    @msenmurugan

    @vincbeck We are also facing the same issue. We are using Airflow 3.1.1rc1 version. It's look like a connection pooling issue. The connection is dying during the execution of this query. This means the connection was already in a compromised state, or something external caused the connection to be severed right when Airflow tried to use it. The error occurs at cursor.execute(statement, parameters), which is the very act of sending the query to the database over an existing connection.

    NOTE: Whenever we restart the API server service, it works. However, after 1 or 2 hour, again getting the same issue. This issue occurs for users that are logging in. If a user already has a opened session, it is working fine. I'm able to reproduce this issue by logging in to the Airflow via incognito mode.

    2025-10-24T15:19:32.079154Z [error    ] Exception on /login/ [POST]    [airflow.providers.fab.www.app] loc=app.py:1744
    Traceback (most recent call last):
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
        self.dialect.do_execute(
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
        cursor.execute(statement, parameters)
    psycopg2.OperationalError: server closed the connection unexpectedly
    	This probably means the server terminated abnormally
    	before or while processing the request.
    
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 2529, in wsgi_app
        response = self.full_dispatch_request()
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 1825, in full_dispatch_request
        rv = self.handle_user_exception(e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 1823, in full_dispatch_request
        rv = self.dispatch_request()
             ^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/flask/app.py", line 1799, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/flask_appbuilder/security/decorators.py", line 36, in wrapped_view
        response = make_response(view(*args, **kwargs))
                                 ^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/flask_appbuilder/security/views.py", line 590, in login
        user = self.appbuilder.sm.auth_user_db(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/auth_manager/security_manager/override.py", line 1956, in auth_user_db
        user = self.find_user(username=username)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/airflow/providers/fab/auth_manager/security_manager/override.py", line 1426, in find_user
        return self.session.scalars(
               ^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1778, in scalars
        return self.execute(
               ^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1717, in execute
        result = conn._execute_20(statement, params or {}, execution_options)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1710, in _execute_20
        return meth(self, args_10style, kwargs_10style, execution_options)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
        return connection._execute_clauseelement(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
        ret = self._execute_context(
              ^^^^^^^^^^^^^^^^^^^^^^
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
        self._handle_dbapi_exception(
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
        util.raise_(
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
        raise exception
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
        self.dialect.do_execute(
      File "/home/airflow/.local/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
        cursor.execute(statement, parameters)
    sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) server closed the connection unexpectedly
    	This probably means the server terminated abnormally
    	before or while processing the request.
    
    [SQL: SELECT ab_user.id, ab_user.first_name, ab_user.last_name, ab_user.username, ab_user.password, ab_user.active, ab_user.email, ab_user.last_login, ab_user.login_count, ab_user.fail_login_count, ab_user.created_on, ab_user.changed_on, ab_user.created_by_fk, ab_user.changed_by_fk 
    FROM ab_user 
    WHERE lower(ab_user.username) = lower(%(lower_1)s)]
    [parameters: {'lower_1': 'admin'}]
    (Background on this error at: https://sqlalche.me/e/14/e3q8)
    
  6. vincbeck commented on Oct 24, 2025

    @vincbeck
    Contributor

    Pinging @potiuk here. It looks related to the errors we encountered when we migrated Fab provider to fab 5. I do not know if you have any idea. I'll try to reproduce it on my side but in case you had some ideas.

  7. potiuk commented on Oct 25, 2025

    @potiuk
    Member

    @msenmurugan -> can you maybe take a look at the server side and see what error you could correlate with the error on the client side ? The issue in this case is that we have no idea what error it is, apparently postgres process got shut-down for some reason. It could be caused for example by too many connections opened and not released and postgress process crashing due to oom (that would be most likely hypothesis).

    What you will also see is a lot of connections opened from the api-server to the database. Also it would be great to know what setup you have - whether you have pgbouncer or not - because the error might be also in the pgbouncer if you happen to have it.

    The issue might also be simply that for example you have very low number of connection pool configured in pgbouncer. Generally - we would need more information about your server side and logs from the server.

  8. added
    priority:highHigh priority bug that should be patched quickly but does not require immediate new release
    on Oct 25, 2025
  9. potiuk commented on Oct 25, 2025

    @potiuk
    Member

    Would love if someone could provide those logs and server-side perspective.

  10. removed
    needs-triagelabel for new issues that we didn't triage yet
    on Oct 30, 2025
  11. vincbeck commented on Oct 30, 2025

    @vincbeck
    Contributor

    Other similar issue: #57534

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

    affected_version:3.1Issues Reported for 3.1area:APIAirflow's REST/HTTP APIarea:autharea:corekind:bugThis is a clearly a bugpriority:highHigh priority bug that should be patched quickly but does not require immediate new release

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions