Update 2019-06-20 A reader tried to use this post to troubleshoot the exact same problem, and contacted me with questions. It turned out the post had errors due to me converting from Blogger. I apologize, and have corrected those errors. Thanks, Jeffrey!*

I had something kind of awful happen last night. I was taking VirtualBox on an mSATA USB storage drive between work and home to do lab testing. I had upgraded VBox at work, but not at home, and made the mistake starting my VM at home before upgrading. Running VMs on two different machines is tenuous, but I didn’t expect to suddenly be faced with my VM unable to boot.

I found that the .vbox file was bad. Most of the snapshot and hard disk elements were missing. I had all the snapshots themselves, but nothing to say how to use them. I was able to get the VM back to booting, but it was to my first snapshot, meaning I’d lost hours of work.

After many false starts, I managed this solution, got myself to my last state, and was able to clone the VM. I didn’t end up with a set of snapshots, but did have the last state of the VM, which mattered the most.

This isn’t a tutorial; it presumes you understand VirtualBox, editing XML, etc. Sorry, but it was more important for me to get this out of my head quickly.

Order of Snapshots

I needed to know the order of my snapshot chain. I didn’t have multiple nests, just one chain, which was lucky. But some of my false starts changed the modified file datetime, so I suddenly couldn’t rely on that (I *know, “*make a backup, fool!”)

(Note: VMDK? Yes, I was using VMware disks in VBox, since ultimately the VM is going into VMware. I don’t think that made any difference, but will use native VDI in the future, then convert the resulting disk to VMDK if needed.)

HxD Hex Editor to the rescue! Snapshot disks are huge, like 35GB, and I needed to peer into them because parent-child info is stored there. Most text editors load the file into memory—very bad for large files. Disk-based editing was the only way. I could have used the excellent UltraEdit, but just needed to see text. HxD loaded the files instantly (literally), and the information I needed was at the top, better viewed bytes/row = 128

# Disk DescriptorFile.version=1.CID=b5058026.parentCID=ffffffff.createType="monolithicSparse"..# Extent description.RW 83886080 SPARSE "Win7ProGold.vmdk"..# The disk Data Base .#DDB..ddb.virtualHWVersion = "4".ddb.adapterType="ide".ddb.uuid.image="3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43".ddb.uuid.parent="00000000-0000-0000-0000-000000000000".ddb.uuid.modification="b042f5da-7fa4-4f1f-a0a1-6820d032819b".ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000".ddb.geometry.cylinders="16383".ddb.geometry.heads="16".ddb.geometry.sectors="63".ddb.geometry.biosCylinders="1024".ddb.geometry.biosHeads="255".ddb.geometry.biosSectors="63"

Manually adding linefeeds at sensible places yields this:

# Disk DescriptorFile.version=1.CID=b5058026.parentCID=ffffffff.createType="monolithicSparse"..
# Extent description.RW 83886080 SPARSE "Win7ProGold.vmdk"..
# The disk Data Base .
# DDB..ddb.virtualHWVersion = "4".
ddb.adapterType="ide".
ddb.uuid.image="3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43".
ddb.uuid.parent="00000000-0000-0000-0000-000000000000".
ddb.uuid.modification="b042f5da-7fa4-4f1f-a0a1-6820d032819b".
ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000".
ddb.geometry.cylinders="16383".
ddb.geometry.heads="16".
ddb.geometry.sectors="63".
ddb.geometry.biosCylinders="1024".
ddb.geometry.biosHeads="255".
ddb.geometry.biosSectors="63"

The important entries are ddb.uuid.image and ddb.uuid.parent. I noted those for each snapshot disk, then made a list of the snapshot UUIDs and their uuid.parent IDs, et voila!

{3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43}.vmdk UUID  parent 00000000-0000-0000-0000-000000000000
{bf1e79c5-69f0-49d6-ae11-05fd4d4e6e5d}.vmdk UUID  parent 3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43
{558ea477-39bd-40c6-953b-2c3c8b961668}.vmdk UUID  parent bf1e79c5-69f0-49d6-ae11-05fd4d4e6e5d
{35dd8ad4-47d0-4033-823f-dbbc8f367d9a}.vmdk UUID  parent 558ea477-39bd-40c6-953b-2c3c8b961668
{81ce7961-fa37-46ef-8ae0-a8461e5ebe1b}.vmdk UUID  parent 35dd8ad4-47d0-4033-823f-dbbc8f367d9a
{0197c2be-2ae3-4599-938d-fcf013b77abb}.vmdk UUID  parent 81ce7961-fa37-46ef-8ae0-a8461e5ebe1b
{2b790ec1-be3a-4a7b-8075-89bc54948825}.vmdk UUID  parent 0197c2be-2ae3-4599-938d-fcf013b77abb

Here's the same info in a tree:

00000000-0000-0000-0000-000000000000
|_3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43
  |_bf1e79c5-69f0-49d6-ae11-05fd4d4e6e5d
    |_558ea477-39bd-40c6-953b-2c3c8b961668
      |_35dd8ad4-47d0-4033-823f-dbbc8f367d9a
        |_81ce7961-fa37-46ef-8ae0-a8461e5ebe1b
          |_0197c2be-2ae3-4599-938d-fcf013b77abb
            |_2b790ec1-be3a-4a7b-8075-89bc54948825

.vbox File

Now, how to update the .vbox file. Without going into the sordid tale…

  1. Remove snapshot info from <Machine> element.
  2. Remove top <Snapshot> element.
  3. Add nested <HardDisk> elements in the correct order.
  4. Set the StorageController <Image> uuid to the last hard disk element’s uuid.

Yuck

Note: The final child snapshot is self-closed XML, terminated by />

<machine laststatechange="2016-02-02T12:16:14Z" snapshotfolder="Snapshots" ostype="Windows7\_64" name="Win7ProGold" uuid="{e21fa63b-d412-4e19-88c8-971ec7bc3ad7}">  
        <mediaregistry>  
          <harddisks>  
            <harddisk uuid="{3b111bc1-9b1e-4b4c-ad00-f4f4a09d7d43}" type="Normal" format="VMDK" location="Win7ProGold.vmdk">  
              <harddisk uuid="{bf1e79c5-69f0-49d6-ae11-05fd4d4e6e5d}" format="VMDK" location="Snapshots/{bf1e79c5-69f0-49d6-ae11-05fd4d4e6e5d}.vmdk">  
                <harddisk uuid="{558ea477-39bd-40c6-953b-2c3c8b961668}" format="VMDK" location="Snapshots/{558ea477-39bd-40c6-953b-2c3c8b961668}.vmdk">  
                  <harddisk uuid="{35dd8ad4-47d0-4033-823f-dbbc8f367d9a}" format="VMDK" location="Snapshots/{35dd8ad4-47d0-4033-823f-dbbc8f367d9a}.vmdk">  
                    <harddisk uuid="{81ce7961-fa37-46ef-8ae0-a8461e5ebe1b}" format="VMDK" location="Snapshots/{81ce7961-fa37-46ef-8ae0-a8461e5ebe1b}.vmdk">  
                      <harddisk uuid="{0197c2be-2ae3-4599-938d-fcf013b77abb}" format="VMDK" location="Snapshots/{0197c2be-2ae3-4599-938d-fcf013b77abb}.vmdk">  
                        <harddisk uuid="{2b790ec1-be3a-4a7b-8075-89bc54948825}" format="VMDK" location="Snapshots/{2b790ec1-be3a-4a7b-8075-89bc54948825}.vmdk" />  
                      </harddisk>  
                    </harddisk>  
                  </harddisk>  
                </harddisk>  
              </harddisk>  
            </harddisk>  
          </harddisks>    
    ...
    
    <StorageControllers>  
      <StorageController name="SATA" type="AHCI" PortCount="2" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">  
        <AttachedDevice type="HardDisk" hotpluggable="false" port="0" device="0">  
          <Image uuid="{2b790ec1-be3a-4a7b-8075-89bc54948825}">  
        </AttachedDevice>

At this point, I could start the VM successfully and clone it, flattening the disk structure.