diff --git a/pkgs/clan-cli/clan_cli/flake.py b/pkgs/clan-cli/clan_cli/flake.py index 7a9aff8b6..3f3e40fdc 100644 --- a/pkgs/clan-cli/clan_cli/flake.py +++ b/pkgs/clan-cli/clan_cli/flake.py @@ -480,4 +480,38 @@ class Flake: if not self._cache.is_cached(selector): log.info(f"Cache miss for {selector}") self.get_from_nix([selector], nix_options) - return self._cache.select(selector) + value = self._cache.select(selector) + + num_loops = 0 + + # Check if all nix store paths exist + # FIXME: If the value is a highly nested structure, this will be slow + def recursive_path_exists_check(val: Any) -> Any: + nonlocal num_loops + if isinstance(val, str): + if val.startswith("/nix/store/"): + path = Path(val) + if not path.exists(): + msg = f"{path} does not exist" + raise ClanError(msg) + + elif isinstance(val, dict): + return {k: recursive_path_exists_check(v) for k, v in val.items()} + elif isinstance(val, list): + return [recursive_path_exists_check(v) for v in val] + if num_loops > 75: + msg = "Maximum recursion depth (75) exceeded while checking paths" + log.warning(msg) + raise ClanError(msg) + num_loops += 1 + return val + + # If there are any paths that don't exist, refresh from nix + try: + recursive_path_exists_check(value) + except ClanError as e: + log.info(f"Path {e} for {selector} does not exist, refreshing from nix") + self.get_from_nix([selector], nix_options) + value = self._cache.select(selector) + + return value