diff --git a/esphome/espidf/bootloader.py b/esphome/espidf/bootloader.py index 2e4a3bfc323..e8319e6a248 100644 --- a/esphome/espidf/bootloader.py +++ b/esphome/espidf/bootloader.py @@ -298,8 +298,11 @@ def _publish(build_dir: Path, key: str, payload: dict) -> Path: def _remove_dir(path: Path) -> None: """Best-effort rmtree with the repo's read-only and retry hardening.""" - with contextlib.suppress(OSError): + try: rmtree(path) + except OSError as err: + # Leftovers are cleared by the daily prune; just leave a trace. + _LOGGER.debug("Could not remove %s: %s", path, err) def _install_into_build(entry: Path) -> Path: diff --git a/tests/unit_tests/test_espidf_bootloader.py b/tests/unit_tests/test_espidf_bootloader.py index 1e238e112e4..a52ba5cc6d4 100644 --- a/tests/unit_tests/test_espidf_bootloader.py +++ b/tests/unit_tests/test_espidf_bootloader.py @@ -707,6 +707,18 @@ def test_prune_removes_only_old_work_dirs(tmp_path: Path) -> None: assert fresh.exists() +def test_remove_dir_logs_a_failed_delete( + tmp_path: Path, caplog: pytest.LogCaptureFixture +) -> None: + """Best-effort cleanup never raises, but leaves a trace.""" + with ( + patch.object(bootloader, "rmtree", side_effect=OSError("busy")), + caplog.at_level("DEBUG"), + ): + bootloader._remove_dir(tmp_path) + assert "Could not remove" in caplog.text + + def test_prune_swallows_cache_root_errors() -> None: """Housekeeping never fails a build.""" with patch.object(bootloader, "_cache_root", side_effect=OSError("gone")):