From c341e9695f33532ee1e43a2b0845b3379345a74c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 18 May 2026 11:55:27 +0200 Subject: [PATCH] HttpBinaryCacheStore: Don't ignore 401/407 errors The only reason it treats 403 errors as 404s is that S3 returns 403 for files that don't exist if the bucket is unlistable. But we don't want to ignore (and definitely shouldn't cache) 401/407 errors as "file not found". This fixes "token expired" errors from cache.flakehub.com being silently ignored and cached. Now you get: # nix build --dry-run /nix/store/qnfhg5anpfpr4il3jlp9bnkf6vhyzbnj-determinate-nix-3.20.0 error: unable to download 'https://cache.flakehub.com/qnfhg5anpfpr4il3jlp9bnkf6vhyzbnj.narinfo': HTTP error 401 response body: {"code":401,"error":"Unauthorized","message":"Unauthorized.","request_id":"019e3a82-2474-7f80-8564-6e1bc2234654"} don't know how to build these paths: /nix/store/qnfhg5anpfpr4il3jlp9bnkf6vhyzbnj-determinate-nix-3.20.0 i.e. it's a fatal error now unless you use `--fallback`. --- src/libstore/filetransfer.cc | 8 ++++++-- src/libstore/include/nix/store/filetransfer.hh | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index c2f3b0e0f93f..092a3420d228 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -685,8 +685,12 @@ struct curlFileTransfer : public FileTransfer if (httpStatus == 404 || httpStatus == 410 || code == CURLE_FILE_COULDNT_READ_FILE) { // The file is definitely not there err = NotFound; - } else if (httpStatus == 401 || httpStatus == 403 || httpStatus == 407) { - // Don't retry on authentication/authorization failures + } else if (httpStatus == 401 || httpStatus == 407) { + err = Unauthorized; + } else if (httpStatus == 403) { + // Don't retry on authentication/authorization failures. + // Note: the only reason we treat this differently from 401/407 is S3 returns 403 if a file doesn't + // exist and the bucket is unlistable. err = Forbidden; } else if (httpStatus == 429) { // 429 means too many requests, so we retry (with a substantially longer delay) diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index 272bc13218d7..76309dff72fa 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -385,7 +385,7 @@ public: void download(FileTransferRequest && request, Sink & sink, std::function resultCallback = {}); - enum Error { NotFound, Forbidden, Misc, Transient, Interrupted }; + enum Error { NotFound, Unauthorized, Forbidden, Misc, Transient, Interrupted }; }; /**