Why wouldn't the sha256 hash change when fetching from a different URL (when updating a package)?

I’m trying to do my first pull request to Nixpkgs to upgrade the docbook5 package from 5.0.1 to 5.1, and when I changed in its default.nix the version line to 5.1,

stdenv.mkDerivation rec {
  pname = "docbook5";
# version = "5.0.1";
  version = "5.1";

  src = fetchurl {
    url = "http://www.docbook.org/xml/${version}/docbook-${version}.zip";
    sha256 = "1iz3hq1lqgnshvlz4j9gvh4jy1ml74qf90vqf2ikbq0h4i2xzybs";

I expected nix-build -A docbook5 to fail by showing the correct hash but it succeeded without errors instead.

Well, of course it didn’t fail because it automatically tried the cached path based on the current sha256 hash, and it built the same package, but with a different name.

trying http://tarballs.nixos.org/sha256/1iz3hq1lqgnshvlz4j9gvh4jy1ml74qf90vqf2ikbq0h4i2xzybs
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  816k  100  816k    0     0   664k      0  0:00:01  0:00:01 --:--:-- 2234k

Replaced the 52 characters of the sha256 hash with zeroes, and now it worked as expected.


sha256 hash with zeroes › that’s why lib.fakeSha256 exists

And because of that not easy workflow (at leas for newbies as me),
I always add a comment above hashes:

# How to obtain hash:
# nix-prefetch-url http://www.docbook.org/xml/<version>/docbook-<version>.zip

But I think something simpler should exist if possible (auto-upgrade check, …).

1 Like

Yup, and these go by the name of fixed-output derivations (though I’m struggling to find this term defined in the official documentation right now … Nix Pills mentions it in passing.)

Yup, but whenever I want to use it I forget whether its camel case or something else, forget about the differences between fakeSha256 and fakeHash, forget whether it’s in lib or somewhere else … so in the end I just use sha256 = "" which IIRC works by design.

1 Like

There was no different name involved. fetchurl and most other fetchers use source as the default name.

I started using a generated name that includes the version for the fetchers to have an easier time invalidating hashes.

1 Like

Thanks! Haven’t heard of this function yet.

Thanks! I just found it in the Nix manual (archive) but I also haven’t remembered it being there to be honest.

Again, this is what I remembered as well, until a couple days ago I had to update another package, and it didn’t work (neither did using a random value). I found the 52 zeroes solution suggested by a Stackoverflow comment.

$ nix-build -A docbook5
error: hash '' has wrong length for hash type 'sha256'

$ nix-build -A docbook5
error: hash 'random' has wrong length for hash type 'sha256'

$ nix-build -A docbook5
error: invalid base-32 hash '7777777777777777777777777777777777777777777777777777'

$ nix-build -A docbook5
these derivations will be built:
building '/nix/store/6x7fbvxhqr4pmcz48fzamavfyhhgmn1c-docbook-5.0.1.zip.drv'...

trying http://www.docbook.org/xml/5.0.1/docbook-5.0.1.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    67  100    67    0     0    172      0 --:--:-- --:--:-- --:--:--   172
100    63  100    63    0     0    116      0 --:--:-- --:--:-- --:--:--   116
100  816k  100  816k    0     0   535k      0  0:00:01  0:00:01 --:--:-- 1399k
hash mismatch in fixed-output derivation '/nix/store/zzp8gm0h65ln7b594b8h3iyismr22s83-docbook-5.0.1.zip':
  wanted: sha256:0000000000000000000000000000000000000000000000000000
  got:    sha256:1iz3hq1lqgnshvlz4j9gvh4jy1ml74qf90vqf2ikbq0h4i2xzybs
cannot build derivation '/nix/store/9a9cd090fzwq4g03mbghphsq68f3n142-docbook5-5.0.1.drv': 1 dependencies couldn't be built
error: build of '/nix/store/9a9cd090fzwq4g03mbghphsq68f3n142-docbook5-5.0.1.drv' failed

Probably the nix-prefetch-url method is the best (but I’ll probably forget it…).

Would you expand on this? I may have been misusing the term name then, but the output path was certainly different, and the name of the derivation can be generated from pname and version since RFC-35 (PR). Then again, whenever I get confident that I understand something NIx-related, I quickly get a reality check…

Is this something akin to RFC-35?

When you do fetchurl { url = …; sha256 = …; } then the name of the derivation is “source”. You need to provide an explicit name argument, eg: fetchurl { name = "${name}-${version}-source"; url = …; sha256 = …; }, to make it aware of changes in the outer derivations version, without having to remember to invalidate the hash manually.

That was about mkDerivation and its variants, though I am talking about the various fetch* helpers to fetch sources.


The support for empty hashes is relatively recent and only works with nixUnstable at the moment. I would recommend using empty hash on unstable Nix, and changing the first character of the hash between 0 and 1 in base32 hashes (or lib.fakeSha256) on stable Nix.

The issue with nix-prefetch-url is that it only works for plain fetchurl. If you prefetch an archive and pass its hash to fetchzip, it will get confused since it expects an extracted directory tree with some post-processing, not an archive.