From 6530f00b0e4a59afdd53dee679896f6eb8712d15 Mon Sep 17 00:00:00 2001 From: Thomas Lockney Date: Mon, 27 Jul 2026 22:40:00 -0700 Subject: [PATCH] emacs: refresh archives and retry when a package install fails Installing magit on a machine whose archive cache was stale failed with "https://elpa.nongnu.org/nongnu/with-editor-3.4.9.tar: Not found". The cache is not wrong about which packages exist, it is wrong about their versions: GNU and nongnu ELPA keep only the current release of each package, so an index that names a superseded version resolves to a tarball the server has deleted. Nothing in the config recovered from that. The refresh added earlier only runs when package-archive-contents is empty, so after the first successful run on a machine the index is never refreshed again. use-package cannot cover for it either -- use-package-ensure-elpa refreshes only when the package is missing from the cache: (if (assoc package package-archive-contents) (package-install package) ; present: install, no refresh (package-refresh-contents) ; absent: refresh, then install (package-install package)) magit was present in the stale cache, so it took the first branch and failed resolving its dependency. Any newly added package hits this on any machine whose cache has aged, and the only recovery was to run M-x package-refresh-contents by hand. package-install now refreshes and retries once on failure. That costs nothing when the cache is fresh, since it only runs on the error path. --- .emacs.d/init.el | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.emacs.d/init.el b/.emacs.d/init.el index 705d16d..6fcd23c 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -39,6 +39,33 @@ (unless package-archive-contents (package-refresh-contents)) +(defun tl/package-install-refresh-on-error (install package &rest args) + "Call INSTALL on PACKAGE, refreshing the archives and retrying once on failure. + +The cached archive index outlives the tarballs it names: nongnu ELPA and GNU +ELPA keep only the current version of each package, so once the cache is +stale, installing anything whose dependency has since been released again +fails with a 404 rather than a missing-package error. + +use-package cannot recover from that on its own. `use-package-ensure-elpa' +refreshes only when the package is absent from `package-archive-contents'; a +package that is present but points at a version the server has deleted goes +straight to `package-install' and fails. Adding magit to this file on a +machine whose cache was weeks old is exactly that case -- it failed on +with-editor-3.4.9.tar, which no longer exists. + +Retrying after a refresh costs nothing when the cache is fresh, and is the +only thing that helps when it is not." + (condition-case err + (apply install package args) + (error + (message "Installing %s failed (%s); refreshing archives and retrying" + package (error-message-string err)) + (package-refresh-contents) + (apply install package args)))) + +(advice-add 'package-install :around #'tl/package-install-refresh-on-error) + ;; compat must exist and be activated before the packages that macro-expand ;; against it are byte-compiled, or the first run dies with ;; "Cannot open load file: compat-NN".