diff --git a/lix/libexpr/flake/lockfile.cc b/lix/libexpr/flake/lockfile.cc index e1379c116..b56c9025b 100644 --- a/lix/libexpr/flake/lockfile.cc +++ b/lix/libexpr/flake/lockfile.cc @@ -1,5 +1,7 @@ #include "lix/libexpr/flake/lockfile.hh" +#include "json-to-value.hh" #include "lix/libstore/store-api.hh" +#include "lix/libutil/error.hh" #include "lix/libutil/url-parts.hh" #include @@ -186,8 +188,16 @@ std::string LockFile::to_string() const LockFile LockFile::read(const Path & path) { - if (!pathExists(path)) return LockFile(); - return LockFile(nlohmann::json::parse(readFile(path)), path); + if (!pathExists(path)) { + return LockFile(); + } + try { + return LockFile(nlohmann::json::parse(readFile(path)), path); + } catch (nlohmann::json::parse_error &nlohmann_json_parse_exc) { + auto json_parse_error = JSONParseError(nlohmann_json_parse_exc.what()); + json_parse_error.addTrace(nullptr, "while parsing the lock file at %s", path); + throw json_parse_error; + } } std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile) diff --git a/tests/functional2/flakes/test_invalid_flake_lock.py b/tests/functional2/flakes/test_invalid_flake_lock.py new file mode 100644 index 000000000..6480364a0 --- /dev/null +++ b/tests/functional2/flakes/test_invalid_flake_lock.py @@ -0,0 +1,30 @@ +from pathlib import Path +from textwrap import dedent +from functional2.testlib.fixtures import Nix +import re + +def test_invalid_flake_lock(nix: Nix, tmp_path: Path): + flake_dir = tmp_path / 'flake' + flake_dir.mkdir() + + (flake_dir / 'flake.nix').write_text(dedent(""" + { + inputs = {}; + outputs = inputs: {}; + } + """)) + (flake_dir / 'flake.lock').write_text(dedent(""" + { + this flake.lock is obviously invalid + } + """)) + + cmd = nix.nix(["build"], flake=True) + cmd.cwd = flake_dir + res = cmd.run().expect(1) + print(res.stderr_plain) + + ERROR_RE1 = re.compile(fr"while updating the lock file of flake 'path:{flake_dir}.+'") + ERROR_RE2 = re.compile(fr"while parsing the lock file at .+") + assert ERROR_RE1.search(res.stderr_plain) + assert ERROR_RE2.search(res.stderr_plain)