Skip to content

Commit ebfc706

Browse files
authored
Improve error messages when Spack finds a too new DB / lockfile (#37614)
This PR ensures that we'll get a comprehensible error message whenever an old version of Spack tries to use a DB or a lockfile that is "too new". * Fix error message when using a too new DB * Add a unit-test to ensure we have a comprehensible error message
1 parent 644a10e commit ebfc706

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

lib/spack/spack/database.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -798,9 +798,8 @@ def check(cond, msg):
798798

799799
# TODO: better version checking semantics.
800800
version = vn.Version(db["version"])
801-
spec_reader = reader(version)
802801
if version > _db_version:
803-
raise InvalidDatabaseVersionError(_db_version, version)
802+
raise InvalidDatabaseVersionError(self, _db_version, version)
804803
elif version < _db_version:
805804
if not any(old == version and new == _db_version for old, new in _skip_reindex):
806805
tty.warn(
@@ -814,6 +813,8 @@ def check(cond, msg):
814813
for k, v in self._data.items()
815814
)
816815

816+
spec_reader = reader(version)
817+
817818
def invalid_record(hash_key, error):
818819
return CorruptDatabaseError(
819820
f"Invalid record in Spack database: hash: {hash_key}, cause: "
@@ -1642,16 +1643,19 @@ class CorruptDatabaseError(SpackError):
16421643

16431644

16441645
class NonConcreteSpecAddError(SpackError):
1645-
"""Raised when attemptint to add non-concrete spec to DB."""
1646+
"""Raised when attempting to add non-concrete spec to DB."""
16461647

16471648

16481649
class MissingDependenciesError(SpackError):
16491650
"""Raised when DB cannot find records for dependencies"""
16501651

16511652

16521653
class InvalidDatabaseVersionError(SpackError):
1653-
def __init__(self, expected, found):
1654-
super(InvalidDatabaseVersionError, self).__init__(
1655-
"Expected database version %s but found version %s." % (expected, found),
1656-
"`spack reindex` may fix this, or you may need a newer " "Spack version.",
1654+
"""Exception raised when the database metadata is newer than current Spack."""
1655+
1656+
def __init__(self, database, expected, found):
1657+
msg = (
1658+
f"you need a newer Spack version to read the database in '{database.root}'. "
1659+
f"The expected database version is '{expected}', but '{found}' was found."
16571660
)
1661+
super(InvalidDatabaseVersionError, self).__init__(msg)

lib/spack/spack/environment/environment.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,10 +2127,12 @@ def _read_lockfile_dict(self, d):
21272127
reader = READER_CLS[current_lockfile_format]
21282128
except KeyError:
21292129
msg = (
2130-
f"Spack {spack.__version__} cannot read environment lockfiles using the "
2131-
f"v{current_lockfile_format} format"
2130+
f"Spack {spack.__version__} cannot read the lockfile '{self.lock_path}', using "
2131+
f"the v{current_lockfile_format} format."
21322132
)
2133-
raise RuntimeError(msg)
2133+
if lockfile_format_version < current_lockfile_format:
2134+
msg += " You need to use a newer Spack version."
2135+
raise SpackEnvironmentError(msg)
21342136

21352137
# First pass: Put each spec in the map ignoring dependencies
21362138
for lockfile_key, node_dict in json_specs_by_hash.items():

lib/spack/spack/test/database.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import spack.repo
3131
import spack.spec
3232
import spack.store
33+
import spack.version as vn
3334
from spack.schema.database_index import schema
3435
from spack.util.executable import Executable
3536

@@ -1051,3 +1052,16 @@ def test_query_installed_when_package_unknown(database, tmpdir):
10511052
assert not s.installed_upstream
10521053
with pytest.raises(spack.repo.UnknownNamespaceError):
10531054
s.package
1055+
1056+
1057+
def test_error_message_when_using_too_new_db(database, monkeypatch):
1058+
"""Sometimes the database format needs to be bumped. When that happens, we have forward
1059+
incompatibilities that need to be reported in a clear way to the user, in case we moved
1060+
back to an older version of Spack. This test ensures that the error message for a too
1061+
new database version stays comprehensible across refactoring of the database code.
1062+
"""
1063+
monkeypatch.setattr(spack.database, "_db_version", vn.Version("0"))
1064+
with pytest.raises(
1065+
spack.database.InvalidDatabaseVersionError, match="you need a newer Spack version"
1066+
):
1067+
spack.database.Database(database.root)._read()

lib/spack/spack/test/env.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,29 @@ def test_initialize_from_random_file_as_manifest(tmp_path, filename):
474474
assert not os.path.exists(env_dir / ev.lockfile_name)
475475
assert os.path.exists(env_dir / ev.manifest_name)
476476
assert filecmp.cmp(env_dir / ev.manifest_name, init_file, shallow=False)
477+
478+
479+
def test_error_message_when_using_too_new_lockfile(tmp_path):
480+
"""Sometimes the lockfile format needs to be bumped. When that happens, we have forward
481+
incompatibilities that need to be reported in a clear way to the user, in case we moved
482+
back to an older version of Spack. This test ensures that the error message for a too
483+
new lockfile version stays comprehensible across refactoring of the environment code.
484+
"""
485+
init_file = tmp_path / ev.lockfile_name
486+
env_dir = tmp_path / "env_dir"
487+
init_file.write_text(
488+
"""
489+
{
490+
"_meta": {
491+
"file-type": "spack-lockfile",
492+
"lockfile-version": 100,
493+
"specfile-version": 3
494+
},
495+
"roots": [],
496+
"concrete_specs": {}
497+
}\n
498+
"""
499+
)
500+
ev.initialize_environment_dir(env_dir, init_file)
501+
with pytest.raises(ev.SpackEnvironmentError, match="You need to use a newer Spack version."):
502+
ev.Environment(env_dir)

0 commit comments

Comments
 (0)