Puzzling behavior of `fetchFromGitHub` with submodules

I encountered a situation where a flake behaves differently depending on previous evaluations. Is this the expected behavior for this case? Or is it an issue with fetchFromGitHub?

I tried to create a minimal reproducible example. The steps are:

  1. Clone the repository GitHub - waltermoreira/fetchsubmodules (it’s a simple flake that fetches another repository containing a git submodule).
  2. Run nix build. It should succeed.
  3. Remove the comment in flake.nix in line 16, thus enabling the fetching of the submodule.
  4. Run nix build. It should also succeed.

Now the flake with the line fetchSubmodules = true commented out builds fine in the system that followed Steps 1 through 4. But the same flake breaks with a hash mismatch on a fresh system (where it wasn’t evaluated before uncommenting Line 16).

It seems that the fixed output derivation

pkgs.fetchFromGitHub {
  owner = "waltermoreira";
  repo = "test-submodules";
  rev = "69b5a04b92e7d483511841c49ea165d6e54d578f";
  hash = "sha256-sU69mCYWy/O+Iphm4BCsSrw6OWqA0V3ox8tSiwjpLK4=";
  # fetchSubmodules = true;
};

is not realized again when we change its parameters (e.g., commenting out fetchSubmodules = true), and it’s happy that the content in the store matches the (now incorrect) hash.

That’s always the case with FODs. If the output path is the same, and the hash is the same, you always get the old result regardless of how the inputs have changed (unless you build with --check, I’ve heard?). Always zero out hashes whenever you change anything about a FOD.

Advanced Attributes - Nix Reference Manual explains this. But there is a speculative PR to modify the name accordingly to avoid such “FOD moments” - fetchFromGitHub: re-fetch upon version changes by ShamrockLee · Pull Request #294068 · NixOS/nixpkgs · GitHub - perhaps fetchSubmodules should be accounted for as well.

Thank you, @rhendric and @waffle8946 . That explains it very well. A bit surprising, I’d say (I like the “FOD moments” expression), but it’s clearly written in the manual.