diff --git a/src/ert/gui/main.py b/src/ert/gui/main.py index 27edc793110..c156286fc34 100755 --- a/src/ert/gui/main.py +++ b/src/ert/gui/main.py @@ -19,7 +19,7 @@ from qtpy.QtGui import QIcon from qtpy.QtWidgets import QApplication, QWidget -from ert.config import ConfigValidationError, ConfigWarning, ErtConfig +from ert.config import ConfigValidationError, ConfigWarning, ErrorInfo, ErtConfig from ert.gui.main_window import ErtMainWindow from ert.gui.simulation import ExperimentPanel from ert.gui.tools.event_viewer import ( @@ -37,7 +37,7 @@ from ert.namespace import Namespace from ert.plugins import ErtPluginManager from ert.services import StorageService -from ert.storage import Storage, open_storage +from ert.storage import ErtStorageException, Storage, open_storage from ert.storage.local_storage import local_storage_set_ert_config from .suggestor import Suggestor @@ -89,6 +89,7 @@ def _start_initial_gui_window( logger = logging.getLogger(__name__) error_messages = [] config_warnings = [] + deprecations = [] ert_config = None with warnings.catch_warnings(record=True) as all_warnings: @@ -116,7 +117,17 @@ def _start_initial_gui_window( and cast(ConfigWarning, w.message).info.is_deprecation ] error_messages += error.errors - logger.info("Error in config file shown in gui: '%s'", str(error)) + if ert_config is not None: + try: + storage = open_storage(ert_config.ens_path, mode="w") + except ErtStorageException as err: + error_messages.append( + ErrorInfo(f"Error opening storage in ENSPATH: {err}").set_context( + ert_config.ens_path + ) + ) + if error_messages: + logger.info(f"Error in config file shown in gui: {error_messages}") return ( Suggestor( error_messages, @@ -131,6 +142,7 @@ def _start_initial_gui_window( ), None, ) + assert ert_config is not None config_warnings = [ cast(ConfigWarning, w.message).info for w in all_warnings @@ -159,7 +171,6 @@ def _start_initial_gui_window( logger.info("Suggestion shown in gui '%s'", msg) for msg in config_warnings: logger.info("Warning shown in gui '%s'", msg) - storage = open_storage(ert_config.ens_path, mode="w") _main_window = _setup_main_window( ert_config, args, log_handler, storage, plugin_manager ) diff --git a/src/ert/storage/__init__.py b/src/ert/storage/__init__.py index 2e2e1c6d892..5fc6a543e79 100644 --- a/src/ert/storage/__init__.py +++ b/src/ert/storage/__init__.py @@ -28,10 +28,19 @@ EnsembleAccessor = LocalEnsemble +class ErtStorageException(Exception): + pass + + def open_storage( path: Union[str, os.PathLike[str]], mode: Union[ModeLiteral, Mode] = "r" ) -> Storage: - return LocalStorage(Path(path), Mode(mode)) + try: + return LocalStorage(Path(path), Mode(mode)) + except Exception as err: + raise ErtStorageException( + f"Failed to open storage: {path} with error: {err}" + ) from err __all__ = [ diff --git a/src/ert/storage/local_storage.py b/src/ert/storage/local_storage.py index 8c16bc601db..28e424e10c5 100644 --- a/src/ert/storage/local_storage.py +++ b/src/ert/storage/local_storage.py @@ -540,7 +540,7 @@ def _storage_version(path: Path) -> int: return int(json.load(f)["version"]) except KeyError as exc: raise NotImplementedError("Incompatible ERT Local Storage") from exc - except FileNotFoundError: + except FileNotFoundError as err: if _is_block_storage(path): return 0 else: diff --git a/tests/unit_tests/storage/test_local_storage.py b/tests/unit_tests/storage/test_local_storage.py index 7a0e1e47826..6580d92fa18 100644 --- a/tests/unit_tests/storage/test_local_storage.py +++ b/tests/unit_tests/storage/test_local_storage.py @@ -1,4 +1,5 @@ import json +import os import shutil import tempfile from dataclasses import dataclass, field @@ -32,7 +33,7 @@ from ert.config.gen_kw_config import TransformFunctionDefinition from ert.config.general_observation import GenObservation from ert.config.observation_vector import ObsVector -from ert.storage import open_storage +from ert.storage import ErtStorageException, open_storage from ert.storage.local_storage import _LOCAL_STORAGE_VERSION from ert.storage.mode import ModeError from ert.storage.realization_storage_state import RealizationStorageState @@ -262,6 +263,14 @@ def test_open_storage_nested_dirs(tmp_path, caplog): assert storage.path.exists() +def test_open_storage_with_corrupted_storage(tmp_path): + with open_storage(tmp_path / "storage", mode="w") as storage: + storage.create_experiment().create_ensemble(name="prior", ensemble_size=1) + os.remove(tmp_path / "storage" / "index.json") + with pytest.raises(ErtStorageException, match="No index.json"): + open_storage(tmp_path / "storage", mode="w") + + def test_that_open_storage_in_read_mode_with_newer_version_throws_exception( tmp_path, caplog ): @@ -270,7 +279,7 @@ def test_that_open_storage_in_read_mode_with_newer_version_throws_exception( storage._save_index() with pytest.raises( - RuntimeError, + ErtStorageException, match=f"Cannot open storage '{tmp_path}': Storage version {_LOCAL_STORAGE_VERSION+1} is newer than the current version {_LOCAL_STORAGE_VERSION}, upgrade ert to continue, or run with a different ENSPATH", ): open_storage(tmp_path, mode="r") @@ -284,7 +293,7 @@ def test_that_open_storage_in_read_mode_with_older_version_throws_exception( storage._save_index() with pytest.raises( - RuntimeError, + ErtStorageException, match=f"Cannot open storage '{tmp_path}' in read-only mode: Storage version {_LOCAL_STORAGE_VERSION-1} is too old", ): open_storage(tmp_path, mode="r") @@ -298,7 +307,7 @@ def test_that_open_storage_in_write_mode_with_newer_version_throws_exception( storage._save_index() with pytest.raises( - RuntimeError, + ErtStorageException, match=f"Cannot open storage '{tmp_path}': Storage version {_LOCAL_STORAGE_VERSION+1} is newer than the current version {_LOCAL_STORAGE_VERSION}, upgrade ert to continue, or run with a different ENSPATH", ): open_storage(tmp_path, mode="w") @@ -534,7 +543,7 @@ def double_open_timeout(self): # already opened with mode="w" somewhere else with patch( "ert.storage.local_storage.LocalStorage.LOCK_TIMEOUT", 0.0 - ), pytest.raises(TimeoutError): + ), pytest.raises(ErtStorageException): open_storage(self.tmpdir + "/storage/", mode="w") @rule()