Btrfs Received UUID set after move/copy to other storage pool or other host

Hi there,

Not sure if it’s a bug or just as designed, but after moving/copying a container residing on a btrfs pool to another storage pool or host (on btrfs too) , it leaves the received_uud set, which is wrong according btrfs itself:

sudo btrfs sub show /storage/root/incus/containers/wifi
WARNING: the subvolume is read-write and has received_uuid set,
         don't use it for incremental send. Please see section
         'SUBVOLUME FLAGS' in manual page btrfs-subvolume for
         further information.
incus/containers/wifi
        Name:                   wifi
        UUID:                   77a79dc7-ae0a-b64a-bcd0-3c05c4493b25
        Parent UUID:            -
        Received UUID:          280a133d-ff1a-1b4f-9b9a-8651a912e523
        Creation time:          2026-06-24 13:35:32 +0200
        Subvolume ID:           4174
        Generation:             1099881
        Gen at creation:        1099875
        Parent ID:              4006
        Top level ID:           4006
        Flags:                  -
        Send transid:           0
        Send time:              2026-06-24 13:35:32 +0200
        Receive transid:        1099880
        Receive time:           2026-06-24 13:35:39 +0200
        Snapshot(s):
        Quota group:            n/a

So shouldn’t incus clear that uuid after moving/copying? Now I have to remember doing it myself or my btrfs backups will fail/complain

Can confirm that, moved a volume between two storages (two different NVMe’s):

❯ sudo btrfs subvolume show /var/lib/root-incus/custom/immich_vol-library/
WARNING: the subvolume is read-write and has received_uuid set,
	 don't use it for incremental send. Please see section
	 'SUBVOLUME FLAGS' in manual page btrfs-subvolume for
	 further information.

Also seen that (different bug):

❯ incus storage create root btrfs source=/var/lib/incusroot/
Error: Only allowed source path under "/var/lib/incus" is "/var/lib/incus/storage-pools/root"

~/projects/incus-compose main* ≡
❯ incus storage create root btrfs source=/var/lib/root-incus/
Storage pool root created

Not sure what this has to do with the received uuid, but for fun I compiled incus myself (which went smoothly :slight_smile: ) and tried it again, but still same issue, so I guess that merge was for something else after all?

That solved the additional bug found by @jochumdev, but unrelated to your first post :slight_smile:
Discourse doesn’t make that clear unfortunately, but I answered his message and not yours.

I researched the original issue:

So the right way for btrfs send/receive to work seems to be:

  • get volumes reversed
  • for volume in volumes { btrfs snapshot <volume> <volume>.tmp }
  • btrfs send
  • delete snapshot

What we are doing on the receive side in createVolumeFromMigrationOptimized incus/internal/server/storage/drivers/driver_btrfs_volumes.go at main · lxc/incus · GitHub

  • receive the subvolume (readonly, received_uuid is set by btrfs)
  • make it read-write with setSubvolumeReadonlyProperty(op.src, false) — btrfs intentionally clears received_uuid at this point
  • move it to the final destination
  • force the received_uuid back with setReceivedUUID(op.dest, op.receivedUUID) — this is the problem

The code is aware of the issue (there’s a comment at line 747-752 explaining it), but the workaround creates exactly the state btrfs warns about:

WARNING: the subvolume is read-write and has received_uuid set,
         don't use it for incremental send.

The fix should be:

  • receive the subvolume (readonly, has received_uuid)
  • btrfs snapshot <received> <dest> (writable snapshot, clean — no received_uuid)
  • move the snapshot to the final destination
  • delete the received original

This avoids the need for setReceivedUUID entirely and gives a clean read-write subvolume.


The send side has a similar pattern in migrateVolumeOptimized. The main volume already gets a temporary snapshot (line 1623-1628, correct). But sendVolume (line 1537-1546) toggles the readonly flag directly on existing snapshots/subvolumes instead of creating temporary snapshots — same “set readonly, send, unset” approach.


@idef1x wanna open a issue for this? This is rather a big change a fix needs extensive testing.

Thanks for digging into it…issue opened: Btrfs Received UUID set after move/copy to other storage pool or other host · Issue #3532 · lxc/incus · GitHub

1 Like