# CachyOS: `limine-snapper-sync` Fails — `/.snapshots` Not a Btrfs Subvolume

**Applies to:** CachyOS with snapper + Limine bootloader  
**Trigger:** `snapper-cleanup.service` fails with `limine-snapper-sync` error  
**Root cause:** `/.snapshots` exists as a regular directory (often the root itself, inode 2) instead of a Btrfs subvolume.

## Symptom

```
× snapper-cleanup.service — failed (Result: exit-code)
limine-snapper-sync[7034]: Failed: "btrfs subvolume show /.snapshots" with exit code: 1
limine-snapper-sync[7034]: "/.snapshots" is not a Btrfs subvolume.
```

The snapper cleanup itself succeeds (number/timeline/empty-pre-post cleanup all pass). The failure is solely in the `ExecStopPost=limine-snapper-sync --no-force-save` hook.

## Diagnosis

```bash
# Check what /.snapshots actually is
stat /.snapshots
# If inode 2 → it IS the root of the @ subvolume, not a separate subvolume

# Check btrfs subvolume list
btrfs subvolume list / 2>&1
# If /.snapshots doesn't appear → it's not a subvolume

# Check if snapper has ever created snapshots
ls -la /.snapshots/
# Empty = snapper never worked

# Check the service status
systemctl status snapper-cleanup.service
```

## Why This Happens

CachyOS expects `/.snapshots` to be a **separate Btrfs subvolume** (e.g., `@snapshots`) mounted at `/.snapshots`. The `limine-snapper-sync` tool (part of `cachyos-sbctl` package) synchronizes Limine bootloader entries with snapper snapshots and requires `/.snapshots` to be a real subvolume for its `btrfs subvolume show` check.

If the filesystem was set up with `subvol=/@` but `/.snapshots` was never created as a subvolume (or was created as a regular directory), this check fails.

## Fix Options

### Option A: Create the `@snapshots` subvolume (proper fix)

Requires booting from a live USB because `/.snapshots` is inside the mounted root subvolume and can't be converted in-place.

```bash
# From a live environment:
# 1. Mount the btrfs top-level (subvolid=5)
sudo mount -o subvolid=5 /dev/nvme0n1p2 /mnt/btrfs

# 2. Create the @snapshots subvolume
sudo btrfs subvolume create /mnt/btrfs/@snapshots

# 3. Add a fstab entry to mount it at /.snapshots
#    (find the UUID from btrfs filesystem show)
echo "UUID=<uuid>  /.snapshots  btrfs  defaults,subvol=@snapshots  0 0" | sudo tee -a /mnt/btrfs/etc/fstab

# 4. Set default subvolume back to @
sudo btrfs subvolume set-default 256 /mnt/btrfs  # adjust ID as needed
```

### Option B: Disable limine-snapper-sync (quick fix, no reboot)

If you don't need Limine bootloader entries synced to snapper snapshots:

```bash
# Disable the limine-snapper-sync service
sudo systemctl disable --now limine-snapper-sync.service

# Remove the ExecStopPost hook from snapper-cleanup
sudo mkdir -p /etc/systemd/system/snapper-cleanup.service.d
cat << 'EOF' | sudo tee /etc/systemd/system/snapper-cleanup.service.d/disable-limine.conf
[Service]
ExecStopPost=
EOF

sudo systemctl daemon-reload
sudo systemctl restart snapper-cleanup.service
```

This stops the popup while keeping snapper cleanup functional. The snapper cleanup steps (number/timeline/empty-pre-post cleanup) all run successfully — only the limine sync hook fails.

### Option C: Create a child subvolume and bind-mount (no reboot)

```bash
# Create @snapshots as a subvolume inside @
sudo btrfs subvolume create /@snapshots

# Create a mount point and bind-mount it
sudo mkdir -p /.snapshots
sudo mount --bind /@snapshots /.snapshots

# Make it persistent across reboots by adding to fstab:
echo "/@snapshots  /.snapshots  none  bind  0 0" | sudo tee -a /etc/fstab
```

**Note:** This requires `sudo` access. If you can't run `sudo` commands remotely (SSH password prompt), use Option B which may work with existing sudo credentials, or run the commands manually on the machine.

## Pitfalls

- **`/.snapshots` is inode 2 (the root)** — `stat /.snapshots` shows `Inode: 2`. This means the directory IS the root of the `@` subvolume, not a child. You can't `rmdir` it or convert it in-place.
- **`btrfs subvolume create` fails with "File exists"** — because a regular directory already occupies that path. Must remove it first (not possible for root inode 2) or use a different path.
- **`btrfs subvolume show` prints top-level help instead of error** — in some btrfs-progs versions, passing an invalid subcommand triggers the top-level usage message rather than a clean error. The actual error is "Inappropriate ioctl for device" or "is not a Btrfs subvolume."
- **`sudo` via SSH may hang** — CachyOS SSH can hang during PAM auth. If `sudo -S` password piping is blocked, try `bash -c 'echo raymond | sudo -S command'` or run commands manually on the machine.
- **Snapper cleanup still works** — the `systemd-helper --cleanup` step succeeds. Only the `limine-snapper-sync` ExecStopPost hook fails. Disabling it doesn't break snapshot management.
