-
Notifications
You must be signed in to change notification settings - Fork 16.4k
Fix scheduler serve_logs subprocess file descriptor errors
#55443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vatsrahul1001
approved these changes
Sep 9, 2025
ashb
reviewed
Sep 9, 2025
amoghrajesh
reviewed
Sep 9, 2025
Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
8667ae7 to
9a0b09e
Compare
serve_logs module import order with lazy app creationserve_logs subprocess file descriptor errors
kaxil
added a commit
to astronomer/airflow
that referenced
this pull request
Sep 9, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
Brunda10
pushed a commit
to Brunda10/airflow
that referenced
this pull request
Sep 17, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Sep 30, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 1, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 2, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 3, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 4, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 5, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 5, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 7, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 8, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 9, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 10, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 11, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 12, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 14, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 15, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 17, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
abdulrahman305 bot
pushed a commit
to abdulrahman305/airflow
that referenced
this pull request
Oct 19, 2025
…e#55443) Remove workers parameter from `uvicorn.run()` in `serve_logs` to fix file descriptor errors when scheduler starts serve_logs as a subprocess. The original implementation used `workers=2` (copied from Gunicorn) but this caused multiprocessing issues in containerized environments. Also implemented lazy app loading via `get_app()` function for better initialization order and architectural consistency with main API. The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing. This regression was introduced in [apache#52581](apache#52581) when serve_logs was refactored from Flask to FastAPI. --- Without this fix, we see following error when running `airflow standalone` fresh in an isolated container: Error 1: ``` scheduler | Traceback (most recent call last): scheduler | File "/.venv/bin/airflow", line 10, in <module> scheduler | sys.exit(main()) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/__main__.py", line 55, in main scheduler | args.func(args) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/cli_config.py", line 49, in command scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/cli.py", line 114, in wrapper scheduler | return f(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/providers_configuration_loader.py", line 54, in wrapped_function scheduler | return func(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 52, in scheduler scheduler | run_command_with_daemon_option( scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/daemon_utils.py", line 86, in run_command_with_daemon_option scheduler | callback() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 55, in <lambda> scheduler | callback=lambda: _run_scheduler_job(args), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 42, in _run_scheduler_job scheduler | with _serve_logs(args.skip_serve_logs), _serve_health_check(enable_health_check): scheduler | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__ scheduler | return next(self.gen) scheduler | File "/.venv/lib/python3.10/site-packages/airflow/cli/commands/scheduler_command.py", line 62, in _serve_logs scheduler | from airflow.utils.serve_logs import serve_logs scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/__init__.py", line 20, in <module> scheduler | from airflow.utils.serve_logs.log_server import create_app scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 160, in <module> scheduler | app = create_app() scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 153, in create_app scheduler | JWTAuthStaticFiles(directory=log_directory, html=False), scheduler | File "/.venv/lib/python3.10/site-packages/airflow/utils/serve_logs/log_server.py", line 49, in __init__ scheduler | super().__init__(*args, **kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/starlette/staticfiles.py", line 56, in __init__ scheduler | raise RuntimeError(f"Directory '{directory}' does not exist") scheduler | RuntimeError: Directory '/root/airflow/logs' does not exist ``` Error 2: This was because we had harcoded 2 workers! but this isn't needed ``` scheduler | Process SpawnProcess-1:53: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor scheduler | Process SpawnProcess-1:54: scheduler | Traceback (most recent call last): scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap scheduler | self.run() scheduler | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run scheduler | self._target(*self._args, **self._kwargs) scheduler | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started scheduler | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage scheduler | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen scheduler | return io.open(fd, mode, buffering, encoding, *args, **kwargs) scheduler | OSError: [Errno 9] Bad file descriptor triggerer | Process SpawnProcess-1:53: triggerer | Traceback (most recent call last): triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap triggerer | self.run() triggerer | File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run triggerer | self._target(*self._args, **self._kwargs) triggerer | File "/.venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 73, in subprocess_started triggerer | sys.stdin = os.fdopen(stdin_fileno) # pragma: full coverage triggerer | File "/usr/local/lib/python3.10/os.py", line 1030, in fdopen triggerer | return io.open(fd, mode, buffering, encoding, *args, **kwargs) triggerer | OSError: [Errno 9] Bad file descriptor ```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Final blocker for 3.1.0b1
Fix scheduler
serve_logssubprocess file descriptor errorsRemove workers parameter from
uvicorn.run()inserve_logsto fix filedescriptor errors when scheduler starts serve_logs as a subprocess.
The original implementation used
workers=2(copied from Gunicorn) butthis caused multiprocessing issues in containerized environments.
Also implemented lazy app loading via
get_app()function for betterinitialization order and architectural consistency with main API.
The primary fix addresses: OSError: [Errno 9] Bad file descriptor. Secondary improvement ensures proper initialization timing.
This regression was introduced in #52581 when serve_logs was refactored from Flask to FastAPI.
Without this fix, we see following error when running
airflow standalonefresh in an isolated container:Error 1:
Error 2:
This was because we had harcoded 2 workers! but this isn't needed