diff --git a/homeassistant/util/yaml/loader.py b/homeassistant/util/yaml/loader.py index 4b7236d7022..a56cf126f79 100644 --- a/homeassistant/util/yaml/loader.py +++ b/homeassistant/util/yaml/loader.py @@ -221,13 +221,21 @@ type LoaderType = FastSafeLoader | PythonSafeLoader def load_yaml( fname: str | os.PathLike[str], secrets: Secrets | None = None ) -> JSON_TYPE | None: - """Load a YAML file.""" + """Load a YAML file. + + If opening the file raises an OSError it will be wrapped in a HomeAssistantError, + except for FileNotFoundError which will be re-raised. + """ try: with open(fname, encoding="utf-8") as conf_file: return parse_yaml(conf_file, secrets) except UnicodeDecodeError as exc: _LOGGER.error("Unable to read file %s: %s", fname, exc) raise HomeAssistantError(exc) from exc + except FileNotFoundError: + raise + except OSError as exc: + raise HomeAssistantError(exc) from exc def load_yaml_dict( diff --git a/tests/util/yaml/test_init.py b/tests/util/yaml/test_init.py index 793ba3183ad..dbd7f1d2e99 100644 --- a/tests/util/yaml/test_init.py +++ b/tests/util/yaml/test_init.py @@ -746,3 +746,24 @@ def test_include_without_parameter(tag: str) -> None: pytest.raises(HomeAssistantError, match=f"{tag} needs an argument"), ): yaml_loader.parse_yaml(file) + + +@pytest.mark.parametrize( + ("open_exception", "load_yaml_exception"), + [ + (FileNotFoundError, OSError), + (NotADirectoryError, HomeAssistantError), + (PermissionError, HomeAssistantError), + ], +) +@pytest.mark.usefixtures("try_both_loaders") +def test_load_yaml_wrap_oserror( + open_exception: Exception, + load_yaml_exception: Exception, +) -> None: + """Test load_yaml wraps OSError in HomeAssistantError.""" + with ( + patch("homeassistant.util.yaml.loader.open", side_effect=open_exception), + pytest.raises(load_yaml_exception), + ): + yaml_loader.load_yaml("bla")