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 with fish (if the binary is present). The only fish-specific bits are variable handling (set NAME value instead of NAME=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:

  1. The GRUB kernel line carries root=UUID=<fs-uuid> ... rootflags=subvol=@. That subvol=@ selects which subvolume becomes /.
  2. With no subvol=, BTRFS falls back to the filesystem's default subvolume (btrfs subvolume get-default, normally subvolid 5 = the top level).
  3. After root mounts, the /etc/fstab inside that subvolume re-asserts subvol=@.

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/cryptroot

Step 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/top

Step 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 /home since the breakage, restoring it is fine. If unsure, skip the @home lines 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/fstab

Step 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


Recovery complete — you're back on 24.04.


Comments