2026-08-24 tmux 3.7c Makes jemalloc Mandatory on macOS
What I set out to do
Run the routine update -c (flake bump + hm switch + GC). It aborted at the
nix flake check gate, so the actual task became unblocking it.
What I actually did
nix flake update moved nixpkgs 391b592 → c8f9065, which carried tmux 3.6a →
3.7c. The build died in configure:
configure: macOS calloc(3) appears not to correctly
configure: zero allocations in some circumstances;
configure: to avoid this, configuring with
configure: --enable-jemalloc is recommended.
configure: error: must give --enable-jemalloc or --disable-jemalloc
tmux 3.7 turned the jemalloc choice into a mandatory flag on Darwin (3.7c
CHANGES: “Build with jemalloc on macOS to avoid what appears to be a bug in
calloc”). nixpkgs bumped the version without passing either flag, so every
Darwin build of home-manager-path failed. Linux is unaffected, which is why
nixpkgs CI let it through. Fourth instance of the same class as
2026-08-04 Obsidian’s DMG Layout Change Blocks hm switch and
2026-07-13 Darwin Nixpkgs Regressions Blocking hm switch.
Upstream had already fixed it:
NixOS/nixpkgs#555604, merged to
master 512b7608 on 2026-08-23 — one day after the rev the nixpkgs-unstable
channel currently points at. So the fix exists but hasn’t reached the channel.
Applied it verbatim as an entry in the flake’s “upstream regressions” overlay
list: link jemalloc, pass --enable-jemalloc.
Version-gated it, because x86_64-darwin (athena) draws tmux 3.6a from
nixpkgs-26.05-darwin, where the flag doesn’t exist and passing it would earn
an unrecognized-option warning plus a gratuitous rebuild.
While in the same block, dropped the obsidian sourceRoot overlay — its comment
said “drop once nixpkgs-unstable advances past dea0d9ee”, and it has: the
current nixpkgs obsidian darwin derivation is now byte-identical to what the
overlay was producing. Dead code.
nix flake check, just check, and hm switch all green; the deployed tmux is
the jemalloc build.
What was striking
The first shape I wrote for the version gate was infinite recursion:
lib.optionalAttrs (isDarwin && versionAtLeast prev.tmux.version "3.7") { tmux = ...; }prev, not final — yet it still cycles, blowing up in
pkgs/top-level/by-name-overlay.nix:58. Computing the overlay’s attribute
names forces the predicate, which forces prev.tmux; nixpkgs resolves by-name
packages through self (the final set), which needs this overlay’s names.
The prev vs final intuition doesn’t save you when the condition sits where
the attribute names are decided. Moving the test into the value — with an
identity else prev.tmux branch — fixes it at zero cost.
Also notable: the two workarounds moved in opposite directions in the same commit. One added because upstream’s fix hasn’t reached the channel, one removed because upstream’s fix finally did. The channel lag, not the upstream repo, is what these overlay entries are really tracking — same lesson as 2026-08-24 Two Ways a Closed Upstream Issue Still Means Keep the Workaround, from earlier today.