Proxmox cloning corrupts the target image - extensive analysis included

santa_on_a_sledge

New Member
Dec 11, 2025
11
1
3
Hello,

I believe I have uncovered a bug related to cloning (either via the Web UI or via `qm clone` command on the node).

Packages installed:

Code:
proxmox-ve: 9.1.0 (running kernel: 6.17.2-1-pve)
pve-manager: 9.1.1 (running version: 9.1.1/42db4a6cf33dac83)
proxmox-kernel-helper: 9.0.4
proxmox-kernel-6.17.2-1-pve-signed: 6.17.2-1
proxmox-kernel-6.17: 6.17.2-1
ceph-fuse: 19.2.3-pve1
corosync: 3.1.9-pve2
criu: 4.1.1-1
frr-pythontools: 10.3.1-1+pve4
ifupdown: not correctly installed
ifupdown2: 3.3.0-1+pmx11
intel-microcode: 3.20250812.1~deb13u1
libjs-extjs: 7.0.0-5
libproxmox-acme-perl: 1.7.0
libproxmox-backup-qemu0: 2.0.1
libproxmox-rs-perl: 0.4.1
libpve-access-control: 9.0.4
libpve-apiclient-perl: 3.4.2
libpve-cluster-api-perl: 9.0.7
libpve-cluster-perl: 9.0.7
libpve-common-perl: 9.0.15
libpve-guest-common-perl: 6.0.2
libpve-http-server-perl: 6.0.5
libpve-network-perl: 1.2.3
libpve-rs-perl: 0.11.3
libpve-storage-perl: 9.1.0
libspice-server1: 0.15.2-1+b1
lvm2: 2.03.31-2+pmx1
lxc-pve: 6.0.5-3
lxcfs: 6.0.4-pve1
novnc-pve: 1.6.0-3
proxmox-backup-client: 4.0.20-1
proxmox-backup-file-restore: 4.0.20-1
proxmox-backup-restore-image: 1.0.0
proxmox-firewall: 1.2.1
proxmox-kernel-helper: 9.0.4
proxmox-mail-forward: 1.0.2
proxmox-mini-journalreader: 1.6
proxmox-offline-mirror-helper: 0.7.3
proxmox-widget-toolkit: 5.1.2
pve-cluster: 9.0.7
pve-container: 6.0.18
pve-docs: 9.1.1
pve-edk2-firmware: not correctly installed
pve-esxi-import-tools: 1.0.1
pve-firewall: 6.0.4
pve-firmware: 3.17-2
pve-ha-manager: 5.0.8
pve-i18n: 3.6.2
pve-qemu-kvm: 10.1.2-4
pve-xtermjs: 5.5.0-3
qemu-server: 9.1.0
smartmontools: 7.4-pve1
spiceterm: 3.4.1
swtpm: 0.8.0+pve3
vncterm: 1.9.1
zfsutils-linux: 2.3.4-pve1

I have configured a LVM-thin storage which is backed by a single 4096 byte sector drive. Fdisk on the node confirms that this size is being used.

I proceeded to create and install a linux VM, using this LVM-thin storage. By default proxmox opts to use 512 emulation inside the guests. Therefore the installer creates an install that uses 512 B sectors, since thats what was exposed to it.

This is what the VM config looks like:
Code:
agent: 1
bios: ovmf
boot: order=scsi0;net0
cores: 4
cpu: host
efidisk0: nvme-lvm-thin:vm-9000-disk-0,efitype=4m,ms-cert=2023,pre-enrolled-keys=1,size=4M
kvm: 1
machine: q35
memory: 4096
meta: creation-qemu=10.1.2,ctime=1765414133
name: ubuntu-golden-22.04
net0: virtio=42:A1:B3:9C:4A:0A,bridge=vmbr0
numa: 0
onboot: 0
ostype: l26
scsi0: nvme-lvm-thin:vm-9000-disk-1,backup=0,cache=none,discard=on,iothread=1,replicate=0,size=15G,ssd=1
scsihw: virtio-scsi-single
smbios1: uuid=9998fcdc-2470-43b4-afb1-2579722d5538
sockets: 1
vmgenid: 2ad01187-0996-4e96-b83a-e63c83ca510b

Everything works well on this VM. Now when I shut it down completely and proceed to clone it and start the new cloned guest without changing anything, it fails to boot.

The reason is that the cloned image is being corrupted in the process. I suspect the reason behind this corruption is the sector size discrepancy. Because the proxmox node sees the associated disk's LV with 4096 byte sector size, but at the same time the actual data on that LV are layed out according to what the guest VM saw - 512 byte sectors.

Indeed, during the time both VMs were shut down and the cloned VM was not yet started, this command clearly says images differ:

Code:
# qemu-img compare /dev/proxmox_vg0/vm-9000-disk-1 /dev/proxmox_vg0/vm-1001-disk-1
Content mismatch at offset 4096!

When I started the freshly cloned VM, i couldnt boot. I suspect something during the cloning touched the partition table and rewrote it according to the proxmox host geometry - with 4096 sector size in mind. !!But lets not forget that the cloned guest VM instead sees 512 B sector size.


So I shut down all VMs and tried to perform manual bit copy of the drive:
Code:
dd if=/dev/proxmox_vg0/vm-9000-disk-1 of=/dev/proxmox_vg0/vm-1001-disk-1 bs=64K conv=noerror,sync status=progress

And then verified with:

Code:
# qemu-img compare /dev/proxmox_vg0/vm-9000-disk-1 /dev/proxmox_vg0/vm-1001-disk-1
Images are identical.

After that, the cloned VM successfully booted and everything worked, however it required this manual step.

______

Note, this is how the source LV looks from the *proxmox host* side:

Code:
# fdisk -l /dev/proxmox_vg0/vm-9000-disk-1
GPT PMBR size mismatch (31457279 != 3932159) will be corrected by write.
Disk /dev/proxmox_vg0/vm-9000-disk-1: 15 GiB, 16106127360 bytes, 3932160 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device                            Boot Start     End Sectors Size Id Type
/dev/proxmox_vg0/vm-9000-disk-1p1          1 3932159 3932159  15G ee GPT

Partition 1 does not start on physical sector boundary.


and the mapped device from the source VM guest:

Code:
$ sudo fdisk -l /dev/sda
Disk /dev/sda: 15 GiB, 16106127360 bytes, 31457280 sectors
Disk model: QEMU HARDDISK   
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: ED066473-BFF8-4803-8FD5-FB16BE2AD585

Device       Start      End  Sectors  Size Type
/dev/sda1     2048  1466367  1464320  715M EFI System
/dev/sda2  1466368  5136383  3670016  1.8G Linux filesystem
/dev/sda3  5136384 31455231 26318848 12.5G Linux filesystem

This is the target VM LV right after clone from the *proxmox host* side:

Code:
# fdisk -l /dev/proxmox_vg0/vm-1001-disk-1
GPT PMBR size mismatch (31457279 != 3932159) will be corrected by write.
Disk /dev/proxmox_vg0/vm-1001-disk-1: 15 GiB, 16106127360 bytes, 3932160 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device                            Boot Start     End Sectors Size Id Type
/dev/proxmox_vg0/vm-1001-disk-1p1          1 3932159 3932159  15G ee GPT

Partition 1 does not start on physical sector boundary.

DIff:

Code:
# cmp -l /dev/proxmox_vg0/vm-9000-disk-1 /dev/proxmox_vg0/vm-1001-disk-1 | head -n 20
               4097   0 300
               4098   0 270
               4099   0 367
               4100   0 264
               4101   0 263
               4102   0 367
               4103   0 232
               4104   0  71
               4105   0 227
               4106   0 164
               4107   0 254
               4108   0 177
               4109   0  30
               4110   0 251
               4111   0 130
               4112   0 163
               4113   0 100
               4114   0 160
               4115   0  30
               4116   0 255


I hope this issue can be resolved.
 
The reason is that the cloned image is being corrupted in the process. I suspect the reason behind this corruption is the sector size discrepancy. Because the proxmox node sees the associated disk's LV with 4096 byte sector size, but at the same time the actual data on that LV are layed out according to what the guest VM saw - 512 byte sectors.

cloning the disk does not care about its contents at all..

I have configured a LVM-thin storage which is backed by a single 4096 byte sector drive. Fdisk on the node confirms that this size is being used.

is this a physical disk? or iSCSI? or ? please provide more data!

could you also post "lvmconfig --typeconfig full | grep -e thin -e zero" and "pveversion -v", thanks!
 
  • Like
Reactions: weehooey-bh
It's a physical NVME disk on the proxmox node connected via PCIe4.
.

Here's lvmconfig:
Code:
# lvmconfig --typeconfig full | grep -e thin -e zero
        wipe_signatures_when_zeroing_new_lvs=1
        thin_pool_metadata_require_separate_pvs=0
        thin_pool_crop_metadata=0
        thin_pool_zero=1
        thin_pool_discards="passdown"
        thin_pool_chunk_size_policy="generic"
        zero_metadata=1
        sparse_segtype_default="thin"
        thin_check_executable="/usr/sbin/thin_check"
        thin_dump_executable="/usr/sbin/thin_dump"
        thin_repair_executable="/usr/sbin/thin_repair"
        thin_restore_executable="/usr/sbin/thin_restore"
        thin_check_options=["-q","--clear-needs-check-flag"]
        thin_repair_options=[""]
        thin_restore_options=[""]
        thin_pool_autoextend_threshold=100
        thin_pool_autoextend_percent=20
        thin_library="libdevmapper-event-lvm2thin.so"
        thin_command="lvm lvextend --use-policies"

The output of "pveversion -v" is already part of the post - the first code block at the start.
 
thanks, that looks correct. can you also post a clone task log?
 
  • Like
Reactions: gmaoret
Here is the clone task log:

Code:
create full clone of drive efidisk0 (nvme-lvm-thin:vm-9000-disk-0)
  Rounding up size to full physical extent 4.00 MiB
  Logical volume "vm-1001-disk-0" created.
  Logical volume proxmox_vg0/vm-1001-disk-0 changed.
create full clone of drive scsi0 (nvme-lvm-thin:vm-9000-disk-1)
  Logical volume "vm-1001-disk-1" created.
  Logical volume proxmox_vg0/vm-1001-disk-1 changed.
transferred 0.0 B of 15.0 GiB (0.00%)
transferred 153.6 MiB of 15.0 GiB (1.00%)
transferred 308.7 MiB of 15.0 GiB (2.01%)
transferred 462.3 MiB of 15.0 GiB (3.01%)
transferred 615.9 MiB of 15.0 GiB (4.01%)
transferred 769.5 MiB of 15.0 GiB (5.01%)
transferred 924.7 MiB of 15.0 GiB (6.02%)
transferred 1.1 GiB of 15.0 GiB (7.02%)
transferred 1.2 GiB of 15.0 GiB (8.02%)
transferred 1.4 GiB of 15.0 GiB (9.02%)
transferred 1.5 GiB of 15.0 GiB (10.03%)
transferred 1.7 GiB of 15.0 GiB (11.03%)
transferred 1.8 GiB of 15.0 GiB (12.03%)
transferred 2.0 GiB of 15.0 GiB (13.03%)
transferred 2.1 GiB of 15.0 GiB (14.04%)
transferred 2.3 GiB of 15.0 GiB (15.04%)
transferred 2.4 GiB of 15.0 GiB (16.04%)
transferred 2.6 GiB of 15.0 GiB (17.04%)
transferred 2.7 GiB of 15.0 GiB (18.05%)
transferred 2.9 GiB of 15.0 GiB (19.05%)
transferred 3.0 GiB of 15.0 GiB (20.05%)
transferred 3.2 GiB of 15.0 GiB (21.05%)
transferred 3.3 GiB of 15.0 GiB (22.06%)
transferred 3.5 GiB of 15.0 GiB (23.06%)
transferred 3.6 GiB of 15.0 GiB (24.06%)
transferred 3.8 GiB of 15.0 GiB (25.07%)
transferred 3.9 GiB of 15.0 GiB (26.07%)
transferred 4.1 GiB of 15.0 GiB (27.07%)
transferred 4.2 GiB of 15.0 GiB (28.07%)
transferred 4.4 GiB of 15.0 GiB (29.08%)
transferred 4.5 GiB of 15.0 GiB (30.08%)
transferred 4.7 GiB of 15.0 GiB (31.08%)
transferred 4.8 GiB of 15.0 GiB (32.08%)
transferred 5.0 GiB of 15.0 GiB (33.09%)
transferred 5.1 GiB of 15.0 GiB (34.09%)
transferred 5.3 GiB of 15.0 GiB (35.09%)
transferred 5.4 GiB of 15.0 GiB (36.09%)
transferred 5.6 GiB of 15.0 GiB (37.10%)
transferred 5.7 GiB of 15.0 GiB (38.10%)
transferred 5.9 GiB of 15.0 GiB (39.10%)
transferred 6.0 GiB of 15.0 GiB (40.10%)
transferred 6.2 GiB of 15.0 GiB (41.11%)
transferred 6.3 GiB of 15.0 GiB (42.11%)
transferred 6.5 GiB of 15.0 GiB (43.11%)
transferred 6.6 GiB of 15.0 GiB (44.11%)
transferred 6.8 GiB of 15.0 GiB (45.12%)
transferred 6.9 GiB of 15.0 GiB (46.12%)
transferred 7.1 GiB of 15.0 GiB (47.12%)
transferred 7.2 GiB of 15.0 GiB (48.12%)
transferred 7.4 GiB of 15.0 GiB (49.13%)
transferred 7.5 GiB of 15.0 GiB (50.13%)
transferred 7.7 GiB of 15.0 GiB (51.13%)
transferred 7.8 GiB of 15.0 GiB (52.14%)
transferred 8.0 GiB of 15.0 GiB (53.14%)
transferred 8.1 GiB of 15.0 GiB (54.14%)
transferred 8.3 GiB of 15.0 GiB (55.14%)
transferred 8.4 GiB of 15.0 GiB (56.15%)
transferred 8.6 GiB of 15.0 GiB (57.15%)
transferred 8.7 GiB of 15.0 GiB (58.15%)
transferred 8.9 GiB of 15.0 GiB (59.15%)
transferred 9.0 GiB of 15.0 GiB (60.16%)
transferred 9.2 GiB of 15.0 GiB (61.16%)
transferred 9.3 GiB of 15.0 GiB (62.16%)
transferred 9.5 GiB of 15.0 GiB (63.16%)
transferred 9.6 GiB of 15.0 GiB (64.17%)
transferred 9.8 GiB of 15.0 GiB (65.17%)
transferred 9.9 GiB of 15.0 GiB (66.17%)
transferred 10.1 GiB of 15.0 GiB (67.17%)
transferred 10.2 GiB of 15.0 GiB (68.18%)
transferred 10.4 GiB of 15.0 GiB (69.18%)
transferred 10.5 GiB of 15.0 GiB (70.18%)
transferred 10.7 GiB of 15.0 GiB (71.18%)
transferred 10.8 GiB of 15.0 GiB (72.19%)
transferred 11.0 GiB of 15.0 GiB (73.19%)
transferred 11.1 GiB of 15.0 GiB (74.19%)
transferred 11.3 GiB of 15.0 GiB (75.20%)
transferred 11.4 GiB of 15.0 GiB (76.20%)
transferred 11.6 GiB of 15.0 GiB (77.20%)
transferred 11.7 GiB of 15.0 GiB (78.20%)
transferred 11.9 GiB of 15.0 GiB (79.21%)
transferred 12.0 GiB of 15.0 GiB (80.21%)
transferred 12.2 GiB of 15.0 GiB (81.21%)
transferred 12.3 GiB of 15.0 GiB (82.21%)
transferred 12.5 GiB of 15.0 GiB (83.22%)
transferred 12.6 GiB of 15.0 GiB (84.22%)
transferred 12.8 GiB of 15.0 GiB (85.22%)
transferred 12.9 GiB of 15.0 GiB (86.22%)
transferred 13.1 GiB of 15.0 GiB (87.23%)
transferred 13.2 GiB of 15.0 GiB (88.23%)
transferred 13.4 GiB of 15.0 GiB (89.23%)
transferred 13.5 GiB of 15.0 GiB (90.23%)
transferred 13.7 GiB of 15.0 GiB (91.24%)
transferred 13.8 GiB of 15.0 GiB (92.24%)
transferred 14.0 GiB of 15.0 GiB (93.24%)
transferred 14.1 GiB of 15.0 GiB (94.24%)
transferred 14.3 GiB of 15.0 GiB (95.25%)
transferred 14.4 GiB of 15.0 GiB (96.25%)
transferred 14.6 GiB of 15.0 GiB (97.25%)
transferred 14.7 GiB of 15.0 GiB (98.26%)
transferred 14.9 GiB of 15.0 GiB (99.26%)
transferred 15.0 GiB of 15.0 GiB (100.00%)
transferred 15.0 GiB of 15.0 GiB (100.00%)
TASK OK

I also tried redoing the whole process with a single additional thing: forcing the source guest VM to use 4096 B sector size, by adding this line to the 9000.conf file:

Code:
args: -set device.scsi0.logical_block_size=4096 -set device.scsi0.physical_block_size=4096

Then, after the installation of the source guest VM, I could see the partitions from the proxmox host correctly with fdisk:
Code:
fdisk -l /dev/proxmox_vg0/vm-9000-disk-1
Disk /dev/proxmox_vg0/vm-9000-disk-1: 15 GiB, 16106127360 bytes, 3932160 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: gpt
Disk identifier: 93882D3A-83DB-4B1E-8CE4-EAFAB105C14C

Device                             Start     End Sectors  Size Type
/dev/proxmox_vg0/vm-9000-disk-1p1    256  183295  183040  715M EFI System
/dev/proxmox_vg0/vm-9000-disk-1p2 183296  642047  458752  1.8G Linux filesystem
/dev/proxmox_vg0/vm-9000-disk-1p3 642048 3931903 3289856 12.5G Linux filesystem


After I shut off that VM and performed a clone, this is what the cloned disk looked like via fdisk from the proxmox node:
Code:
fdisk -l /dev/proxmox_vg0/vm-1001-disk-1
Disk /dev/proxmox_vg0/vm-1001-disk-1: 15 GiB, 16106127360 bytes, 3932160 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device                            Boot Start     End Sectors Size Id Type
/dev/proxmox_vg0/vm-1001-disk-1p1          1 3932159 3932159  15G ee GPT

Partition 1 does not start on physical sector boundary.
 
Last edited:
this sounds like an instance of "hole" mishandling, which is often caused by devices lying about their support for discarding. changing the block size might just cause the data to be aligned differently by the guest OS and thus avoid the issue..

you could try running the clone under strace:
1. first, find out the exact `qemu-img convert` commandline used by cloning
2. create a new LV on the target storage
3. run `strace -ff -o /tmp/strace_ <qemu-img convert command with the target device path replaced by the new LV>`
4. post the strace files here (they are probably big, and they might contain traces of the LV contents, so if you are worried about that, you can also drop me an email at f.gruenbichler@proxmox.com and tell me how to access them directly).
 
  • Like
Reactions: Johannes S
I noticed that cloning the VM used this command:

Code:
/usr/bin/qemu-img convert -p -n -f raw -O raw /dev/proxmox_vg0/base-9000-disk-1 zeroinit:/dev/proxmox_vg0/<VM_LV_NAME>

This completed normally, without an error despite the content mismatch when later tested with qemu-img compare.

However this command, without the zeroinit prefix errored out right away at some offset, so I guessed it might indicate the error better and ran strace on that command instead:

Code:
/usr/bin/qemu-img convert -p -n -f raw -O raw /dev/proxmox_vg0/base-9000-disk-1 /dev/proxmox_vg0/test_lv

Note, I ran it with -s 0 flag to truncate strings. I'll send you link to an archive of the logs over PM.
 
how did that second command error out? the error is not contained in the strace because of the string censoring ;) could you run strace on the first command as well? thanks!

I suspect the erroring out was caused by:

Code:
1175:ioctl(8, BLKZEROOUT, [2147479552, 3584]) = -1 EINVAL (Invalid argument)

at the end of the strace of 1024696, but for LVM thin zeroinit: should be correct, as LVM should zero every extent before assigning it to a thin LV
 
Hello,

I do not remember the exact byte offset, but the error message was: qemu-img: error while writing at byte xxxxxx: Invalid argument.

I deleted the LVM thin pool altogether.

In the meantime I found out the same error is caused on disks on a thick provisioned LVs too, with only exception that it correctly fails during the cloning operation (instead of silently not failing and reporting the task as OK in case of LVM thin). Note that both the thin and thick provisioned LVs are backed by the same physical NVME drive with 4k sector size.

Here is the task log from the proxmox web UI for cloning a template VM (all source and target LVs involved are thick provisioned):

Code:
create full clone of drive efidisk0 (nvme-lvm:vm-9000-disk-0)
  Rounding up size to full physical extent 4.00 MiB
  Logical volume "vm-5000-disk-0" created.
create full clone of drive scsi0 (nvme-lvm:vm-9000-disk-1)
  Logical volume "vm-5000-disk-1" created.
transferred 0.0 B of 15.0 GiB (0.00%)
transferred 153.6 MiB of 15.0 GiB (1.00%)
transferred 308.7 MiB of 15.0 GiB (2.01%)
transferred 462.3 MiB of 15.0 GiB (3.01%)
transferred 615.9 MiB of 15.0 GiB (4.01%)
transferred 769.5 MiB of 15.0 GiB (5.01%)
transferred 924.7 MiB of 15.0 GiB (6.02%)
transferred 1.1 GiB of 15.0 GiB (7.02%)
transferred 1.2 GiB of 15.0 GiB (8.02%)
transferred 1.4 GiB of 15.0 GiB (9.02%)
transferred 1.5 GiB of 15.0 GiB (10.03%)
transferred 1.7 GiB of 15.0 GiB (11.03%)
transferred 1.8 GiB of 15.0 GiB (12.03%)
transferred 2.0 GiB of 15.0 GiB (13.03%)
transferred 2.1 GiB of 15.0 GiB (14.04%)
transferred 2.3 GiB of 15.0 GiB (15.04%)
transferred 2.4 GiB of 15.0 GiB (16.04%)
qemu-img: error while writing at byte 2627730944: Invalid argument
  Logical volume "vm-5000-disk-0" successfully removed.
  Logical volume "vm-5000-disk-1" successfully removed.
TASK ERROR: clone failed: copy failed: command '/usr/bin/qemu-img convert -p -n -f raw -O raw /dev/proxmox_vg0/vm-9000-disk-1 /dev/proxmox_vg0/vm-5000-disk-1' failed: exit code 1

I ran this:

Code:
strace -s 0 -ff -o /tmp/strace_logs/strace_ /usr/bin/qemu-img convert -p -n -f raw -O raw /dev/proxmox_vg0/vm-9000-disk-1 /dev/proxmox_vg0/test_lv

Output:
Code:
qemu-img: error while writing at byte 2627730944: Invalid argument

Redacted strace log files in your mailbox.
 
A note: the byte offset in the error message: 2627730944 is not divisible by the physical hard drive sector size (4096).

I think this issue is caused by the qemu-img failing to handle the 4K native sector size.
 
Definitely an upstream issue, red hats bugzilla has numerous 4k errors for qemu img convert failing similarly... Unfortunately this just leaves me unable to clone a VM because it destroys the whole VM on task error and I cant manually make a "dumb" dd copy of the source VM disk onto the target one.
 
could you still file an issue in our bugzilla with the details (and maybe some references to those upstream reports)?
 
For anyone struggling with this right now, I advise to create a wrapper script in place of /usr/bin/qemu-img to insert the "-S 0" flag for the convert subcommand. This disables the intelligent sparse detection completely but at least the cloning does not fail.