Booting Back Out of a Bad Timeshift Snapshot (Pop!_OS + BTRFS)
I upgraded a Pop!_OS box from 22.04 LTS to 24.04 LTS, hit a snag, and reached
for Timeshift to "restore" an older snapshot. It booted — into the old system
— and then every subsequent boot dropped me into the systemd emergency
shell. systemd-modules-load.service was failing with "Failed to look up
module alias … Function not implemented" (ENOSYS), vfat wouldn't load, and so
/boot/efi couldn't mount. One illness, several symptoms.
The root cause: Timeshift's BTRFS restore doesn't roll back in place — it
swaps subvolumes, so the old snapshot became my live root (@). The booted
system's /lib/modules no longer matched the running kernel, which is why module
loading died and the FAT EFI partition couldn't be mounted.
Below is the full recovery, in fish-shell syntax, from the emergency shell back to a clean 24.04 boot.
Shell note: the systemd emergency shell is usually
bash/sh. To use these exact commands, start fish first withfish(if the binary is present). The only fish-specific bits are variable handling (set NAME valueinstead ofNAME=value, and command substitution with(...)instead of$(...)); everything else is identical to bash.
How BTRFS "chooses" what to boot
BTRFS doesn't choose — the bootloader and mount options do:
- The GRUB kernel line carries
root=UUID=<fs-uuid> ... rootflags=subvol=@. Thatsubvol=@selects which subvolume becomes/. - With no
subvol=, BTRFS falls back to the filesystem's default subvolume (btrfs subvolume get-default, normally subvolid 5 = the top level). - After root mounts, the
/etc/fstabinside that subvolume re-assertssubvol=@.
On Ubuntu/Pop the live system is the subvolume named @ (home is @home).
The fix is to put your good 24.04 system back at @ so the existing subvol=@
boot entry lands on the right system. Timeshift snapshots are read-only, so
you can't boot one directly — you create a fresh writable @ from the
snapshot.
Step 1 — Identify the BTRFS device
btrfs filesystem show
lsblk -f
Note the device for your root filesystem (e.g. /dev/nvme0n1p3). If it's
LUKS-encrypted, unlock it first:
cryptsetup luksOpen /dev/nvme0n1pX cryptroot # then use /dev/mapper/cryptrootStep 2 — Mount the top-level subvolume (subvolid=5)
This exposes every subvolume, not just the currently-booted one.
mkdir -p /mnt/top
mount -o subvolid=5 /dev/nvme0n1p3 /mnt/top
ls -la /mnt/topStep 3 — List all subvolumes
btrfs subvolume list /mnt/top
You'll see your live @ and @home, plus Timeshift snapshots under
timeshift-btrfs/snapshots/<timestamp>/@ and .../@home.
Step 4 — Pick the snapshot and VERIFY it's the 24.04 system
Don't trust names — check the contents before changing anything. In fish, set the
variable with set and use (...) for any command substitution:
ls /mnt/top/timeshift-btrfs/snapshots/
set SNAP /mnt/top/timeshift-btrfs/snapshots/2026-06-19_XX-XX-XX # your real timestamp
grep VERSION= $SNAP/@/etc/os-release # expect VERSION="24.04..."
ls $SNAP/@/lib/modules # expect a 24.x kernel directory
Or loop over every candidate subvolume at once (fish for ... end):
for s in /mnt/top/@*
echo "=== $s ==="
grep VERSION= $s/etc/os-release
ls $s/lib/modules
end
Proceed only once you've confirmed which subvolume is the 24.04 system.
Step 5 — Move the broken subvolumes aside (rename, never delete)
cd /mnt/top
mv @ @broken-2204
mv @home @home-broken-2204
Keeping them (renamed) makes this whole operation reversible.
Step 6 — Create new WRITABLE subvolumes from the snapshot
btrfs subvolume snapshot $SNAP/@ /mnt/top/@
btrfs subvolume snapshot $SNAP/@home /mnt/top/@home
No -r flag → these are read-write, which is what a root filesystem requires.
The original snapshots stay untouched as backups.
Note on
@home: only restore it if the snapshot's home is the version you want. If you've created nothing in/homesince the breakage, restoring it is fine. If unsure, skip the@homelines and keep your current@home— the system will still boot.
Step 7 — Sanity-check the mount options
The new @ came from a system that already used subvol=@, so its /etc/fstab
and the GRUB entry should already agree. Quick confirm:
grep -E 'subvol' /mnt/top/@/etc/fstabStep 8 — Reboot
cd /
umount /mnt/top
reboot
GRUB still points at subvol=@, but @ is now your real 24.04 root with a
kernel that matches its /lib/modules. Module loading works → vfat loads →
/boot/efi mounts → boot completes.
Step 9 — Confirm success and clean up
After a clean graphical/login boot:
grep VERSION /etc/os-release # 24.04
systemctl --failed # should be empty
findmnt /boot/efi # mounted
uname -r; ls /lib/modules # kernel matches a modules dir
Once you're confident, delete the leftovers:
sudo btrfs subvolume delete /@broken-2204
sudo btrfs subvolume delete /@home-broken-2204
(Mount subvolid=5 again if you need the top-level path to reach them.)
Troubleshooting
- Drops right back to emergency: a unit is still failing. Run
systemctl --failedandjournalctl -b -p err. A failed*.mountusually means a stale UUID/PARTUUID in/etc/fstab— compare againstblkid. Addnofailto non-critical mounts (like/boot/efi,/recovery) so a missing mount can't abort the whole boot. - "Function not implemented" on modprobe: confirms a kernel/modules mismatch — i.e. you're still on the wrong subvolume. Re-check Step 4.
- GRUB itself is broken after the swap: boot a live USB, mount the top-level,
mount --bind/dev /proc /sys, chroot into@, thenupdate-grub && grub-install. - Never run
btrfs check --repairfirst — usebtrfs check --readonlyto diagnose;--repaircan worsen damage.
Recovery complete — you're back on 24.04.
Comments