This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 165b4956988 Distinguish empty plugin folder from plugin load failures 
in logs (#72432)
165b4956988 is described below

commit 165b495698876d0c3aa36acb2ccabfa9f8ed01d7
Author: SreeCharan Desu <[email protected]>
AuthorDate: Tue Sep 8 16:48:15 2026 +0530

    Distinguish empty plugin folder from plugin load failures in logs (#72432)
    
    Empty plugins/ on a new install looked like a failure in the
    summary line even when nothing was wrong; warn only when imports
    actually fail.
---
 airflow-core/src/airflow/plugins_manager.py        | 11 ++++++++++-
 .../tests/unit/plugins/test_plugins_manager.py     | 23 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/airflow-core/src/airflow/plugins_manager.py 
b/airflow-core/src/airflow/plugins_manager.py
index ff3c620b934..ccc29fa8288 100644
--- a/airflow-core/src/airflow/plugins_manager.py
+++ b/airflow-core/src/airflow/plugins_manager.py
@@ -133,7 +133,16 @@ def _get_plugins() -> tuple[list[AirflowPlugin], dict[str, 
str]]:
         if not settings.LAZY_LOAD_PROVIDERS:
             __register_plugins(*_load_providers_plugins())
 
-    log.debug("Loading %d plugin(s) took %.2f ms", len(plugins), 
timer.duration)
+    if import_errors:
+        log.warning(
+            "Failed to load %d plugin file(s): %s",
+            len(import_errors),
+            sorted(import_errors.keys()),
+        )
+    elif not plugins:
+        log.debug("No plugins loaded (plugins folder is empty or contains no 
valid plugins)")
+    else:
+        log.debug("Loading %d plugin(s) took %.2f ms", len(plugins), 
timer.duration)
     return plugins, import_errors
 
 
diff --git a/airflow-core/tests/unit/plugins/test_plugins_manager.py 
b/airflow-core/tests/unit/plugins/test_plugins_manager.py
index 7f458ef4d90..bef30bcd253 100644
--- a/airflow-core/tests/unit/plugins/test_plugins_manager.py
+++ b/airflow-core/tests/unit/plugins/test_plugins_manager.py
@@ -91,6 +91,28 @@ class TestPluginsManager:
 
         assert [r for r in caplog.record_tuples if not 
r[0].startswith("opentelemetry.")] == []
 
+    def test_empty_plugins_folder_logs_no_failure(self, caplog, tmp_path):
+        from airflow import plugins_manager
+
+        with (
+            caplog.at_level(logging.DEBUG, logger="airflow.plugins_manager"),
+            conf_vars(
+                {
+                    ("core", "plugins_folder"): os.fspath(tmp_path),
+                    ("core", "load_examples"): "False",
+                }
+            ),
+            mock.patch("airflow.plugins_manager._load_entrypoint_plugins", 
return_value=([], [])),
+            mock.patch("airflow.plugins_manager._load_providers_plugins", 
return_value=([], [])),
+        ):
+            plugins, import_errors = plugins_manager._get_plugins()
+
+        assert plugins == []
+        assert import_errors == {}
+        received_logs = caplog.text
+        assert "Failed to load" not in received_logs
+        assert "No plugins loaded" in received_logs
+
     def test_loads_filesystem_plugins_exception(self, caplog, tmp_path):
         from airflow import plugins_manager
 
@@ -108,6 +130,7 @@ class TestPluginsManager:
 
         received_logs = caplog.text
         assert "Failed to load plugin" in received_logs
+        assert "Failed to load 1 plugin file(s)" in received_logs
         assert "testplugin.py" in received_logs
 
     def 
test_duplicate_plugin_name_does_not_prevent_loading_subsequent_plugins(self):

Reply via email to