Skip to content

[BUG] POST /auth/token returns 500 - HookMetaService.MockOptional is not callable when FAB initializes AppBuilder #63803

@wangxiaojun1990

Description

@wangxiaojun1990

Apache Airflow version

apache-airflow==3.1.8
apache-airflow-providers-fab==3.4.0
apache-airflow-providers-standard==1.12.0

What happened

POST /auth/token always returns 500 Internal Server Error.

The FAB auth manager calls get_application_builder() on every token request, which initializes Flask-AppBuilder and calls register_views(). During form initialization, HookMetaService.MockOptional instances are passed as WTForms validators. Since MockOptional has no __call__ method, WTForms raises TypeError.

Root Cause

HookMetaService._get_hooks_with_mocked_fab() patches wtforms.validators.Optional with MockOptional class:

with mock.patch("wtforms.validators.Optional", HookMetaService.MockOptional):
    pm = ProvidersManager()  # providers call Optional() → creates MockOptional() instances
    return pm.hooks, pm.connection_form_widgets, ...

After the with block exits, MockOptional() instances remain stored inside provider form widget definitions. When FAB later initializes real WTForms forms using those definitions, check_validators requires validators to be callable — but MockOptional instances are not.

Traceback

File "airflow/providers/fab/auth_manager/api_fastapi/routes/login.py", line 42, in create_token
    with get_application_builder():
File "airflow/providers/fab/auth_manager/cli_commands/utils.py", line 69, in get_application_builder
File "airflow/providers/fab/www/extensions/init_appbuilder.py", line 156, in __init__
File "airflow/providers/fab/auth_manager/fab_auth_manager.py", line 624, in register_views
File "airflow/providers/fab/auth_manager/security_manager/override.py", line 472, in register_views
File "flask_appbuilder/baseviews.py", line 904, in _init_forms
File "wtforms/fields/core.py", line 171, in check_validators
TypeError: <airflow.api_fastapi.core_api.services.ui.connections.HookMetaService.MockOptional object at 0x...>
          is not a valid validator because it is not callable

Expected behavior

POST /auth/token should return a valid JWT token.

Suggested fix

Add __call__ to MockOptional so it is usable as a WTForms validator:

class MockOptional:
    """Mock for wtforms.validators.Optional."""

    def __init__(self, *args, **kwargs):
        pass

    def __call__(self, form, field):
        pass  # no-op

How to reproduce

  1. Deploy Airflow 3.1.8 with apache-airflow-providers-fab==3.4.0
  2. POST http://<airflow-api-server>/auth/token with valid credentials
  3. Observe 500 Internal Server Error

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions