Skip to content

Conversation

@cyp0633
Copy link

@cyp0633 cyp0633 commented Oct 23, 2025

The Background

When deleting an old snapshot in BTRFS mode, the current version of Timeshift deletes certain subdirectories as subvolumes recursively (here):

		subpath = path_combine(path, name);
		if (dir_exists(subpath)) { // there is a nested subvol to remove first
			cmd = "btrfs subvolume delete %s '%s'".printf(options, subpath);
			log_debug("Deleting nested subvolume in snapshot");
			log_debug(cmd);
			ret_val = exec_sync(cmd, out std_out, out std_err);
			if (ret_val != 0){
				log_error(std_err);
				log_error(_("Failed to delete snapshot nested subvolume") + ": '%s'".printf(path));
				return false;
			}
		}

In this way, Timeshift correctly handles situations like timeshift-btrfs/snapshots/xxx/@/@. However, btrfs-progs cannot delete an ordinary directory like a subvolume:

$ mkdir test
$ sudo btrfs subvolume delete test
ERROR: Not a Btrfs subvolume: Invalid argument

The Problem

Similarly, if a /@ directory gets a snapshot, then Timeshift would treat it as a subvolume when deleting the snapshot. Steps to reproduce:

$ sudo mkdir /@ 

$ sudo timeshift --create # the snapshot with @
Using system disk as snapshot device for creating snapshots in BTRFS mode
Mounted '/dev/nvme0n1p2' (subvolid=0) at '/run/timeshift/114861/backup'
btrfs: Quotas are not enabled
Creating new backup...(BTRFS)
Saving to device: /dev/nvme0n1p2, mounted at path: /run/timeshift/114861/backup
Created directory: /run/timeshift/114861/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41
Created subvolume snapshot: /run/timeshift/114861/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41/@
Created subvolume snapshot: /run/timeshift/114861/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41/@home
Created control file: /run/timeshift/114861/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41/info.json
BTRFS Snapshot saved successfully (0s)
Tagged snapshot '2025-10-23_17-05-41': ondemand
------------------------------------------------------------------------------

$ sudo timeshift --delete --snapshot 2025-10-23_17-05-41
Mounted '/dev/nvme0n1p2' (subvolid=0) at '/run/timeshift/114951/backup'
btrfs: Quotas are not enabled
------------------------------------------------------------------------------
Removing snapshot: 2025-10-23_17-05-41
Deleting subvolume: @home (Id:835)
Deleted subvolume: @home (Id:835)

Deleting subvolume: @ (Id:834)
E: ERROR: Not a Btrfs subvolume: Invalid argument # tries to delete subvolumes recursively, but meets a directory

E: Failed to delete snapshot nested subvolume: '/run/timeshift/114951/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41/@'
E: Failed to remove snapshot: 2025-10-23_17-05-41
------------------------------------------------------------------------------

$ sudo rm -rf /@

$ sudo timeshift --create
Using system disk as snapshot device for creating snapshots in BTRFS mode
Mounted '/dev/nvme0n1p2' (subvolid=0) at '/run/timeshift/115103/backup'
btrfs: Quotas are not enabled
Creating new backup...(BTRFS)
Saving to device: /dev/nvme0n1p2, mounted at path: /run/timeshift/115103/backup
Created directory: /run/timeshift/115103/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16
Created subvolume snapshot: /run/timeshift/115103/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16/@
Created subvolume snapshot: /run/timeshift/115103/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16/@home
Created control file: /run/timeshift/115103/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16/info.json
BTRFS Snapshot saved successfully (0s)
Tagged snapshot '2025-10-23_17-08-16': ondemand
------------------------------------------------------------------------------

$ sudo timeshift --delete --snapshot 2025-10-23_17-08-16  
Mounted '/dev/nvme0n1p2' (subvolid=0) at '/run/timeshift/115177/backup'
btrfs: Quotas are not enabled
------------------------------------------------------------------------------
Removing snapshot: 2025-10-23_17-08-16
Deleting subvolume: @home (Id:837)
Deleted subvolume: @home (Id:837)

Deleting subvolume: @ (Id:836)
Deleted subvolume: @ (Id:836)

Deleted directory: /run/timeshift/115177/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16
Deleted directory: /run/timeshift/115177/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16
Deleted directory: /run/timeshift/115177/backup/timeshift-btrfs/snapshots/2025-10-23_17-08-16
Removed snapshot: 2025-10-23_17-08-16
------------------------------------------------------------------------------

I suspect there have been similar problems around for a while:

The Fix

My proposal first checks if there's indeed a subvolume before running btrfs subvolume delete. btrfs subvolume show outputs nothing to the stdout if there's not a subvolume. After applying the fix, the previously failing deletion succeeded:

$ sudo ./timeshift --delete --snapshot 2025-10-23_17-05-41 # using my self-compiled binary
Mounted '/dev/nvme0n1p2' (subvolid=0) at '/run/timeshift/115404/backup'
btrfs: Quotas are not enabled
------------------------------------------------------------------------------
Removing snapshot: 2025-10-23_17-05-41
Deleting subvolume: @ (Id:834)
Deleted subvolume: @ (Id:834)

Deleted directory: /run/timeshift/115404/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41
Deleted directory: /run/timeshift/115404/backup/timeshift-btrfs/snapshots/2025-10-23_17-05-41
Removed snapshot: 2025-10-23_17-05-41
------------------------------------------------------------------------------

Environment:

  • OS: EndeavourOS, Linux 6.17.4-arch2-1
  • Timeshift: 25.07.7
  • btrfs-progs: 6.17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant