Repository: archlinux/archinstall

Issue:
Throws error when using manual partitioning 
I dual boot windows and arch, having to need windows for genshin impact. Anyways today I booted up my xfce install and the panel was broken. So I booted up the arch iso and ran 
```shell
archinstall
``` 
Here is my config:
```shell
 Archinstall lang     English
 Mirrors              Defined 
 Locales              Defined
 Disk configuration   Manual Partitioning 
 Disk encryption
 Bootloader           Systemd-boot
 Swap                 True
 Hostname             archlinux
 Root password
 User account         1 User(s)
 Profiles             Desktop
 Sound server         Pulseaudio
 Kernels              linux-zen
 Additional packages
 Network config       use NetworkManager
 Timezone             UTC
 Optional repositories
``` 

Under manual partitioning I formatted the boot, root and home partitions. I then assigned the mountpoints as follows:
 sda1: /boot 
 sda2: /
 sda3: /home

I attempted to install it and I get this error almost right away:
ValueError: Filesystem must be set for modification

The problem is I did that already in manual partitioning.
Version 2.6.0 of archinstall 

archinstall formats the existing partition though i didn't marked it for formatting
latest 20230801.

archinstall formats the existing partition though I didn't marked it for formatting.

It should indicate in the table what it's going to format.

In my case it was sdb4, see on screenshots:

![PXL_20230806_173402843](https://github.com/archlinux/archinstall/assets/6976920/5bad9d3e-3398-4f8b-a0d2-3b601c541110)

![PXL_20230806_173536445_](https://github.com/archlinux/archinstall/assets/6976920/f668b45b-a223-4e47-bc25-007276a3d97f)



Discussion:
What does the `lsblk` command say? 
Have you tried using a default partitioning, best effort scheme?

I do not have access to the computer currently, but I will update in a few days. The default partitioning works, but like I said I have windows with a large game installed and that will delete the windows partitions. 
As a quick fix, do not set the Sound server as an option but leave it empty. This might help

This fix did not work. I ended up backing up genshin to a hard drive and wiped windows. Any ideas of why this happens?
Do you get the same error when you use a suggested layout? 
you can also store the install config file. I would suggest storing it and inspect it. Maybe you can find a problem with your disk layout 
No, I don't get the error when using suggested layout. I will try this in a vm to see if I can find a fix and will inform at a later date. I yet again am on vacation.
Same issue here, I'm tryin to dual-boot with Windows and it throws that error. Before this I've tried installing Arch on a VM - I didn't get this error when using a suggested layout and wiping the virtual disk, so that's definitely a problem specifically with manual partitioning.
In that case, the config file would be very helpful to investigate
İ am having the same issue. While using suggested partition there is no problem. But using manuel i get error. İ am trying dual boot.
I also forgot to mention that this was not an issue in previous versions of archinstall. Because the day before I attempted to reinstall, I had installed arch using archinstall with no issues. Clearly an update messed it up. 
> I also forgot to mention that this was not an issue in previous versions of archinstall. Because the day before I attempted to reinstall, I had installed arch using archinstall with no issues. Clearly an update messed it up. 

Did you do it dual boot? İ still cannot install dual boot.
Yes I did. I am still trying to find a way to downgrade. My recommendation is if you want to use archinstall go back to version 2.5.0 if possible for now
@inmymum sorry for the late reply, but if you still have the log file that would help immensely with the debugging. After you get the error could you share the file `/var/log/archinstall/install.log` 
> @inmymum sorry for the late reply, but if you still have the log file that would help immensely with the debugging. After you get the error could you share the file `/var/log/archinstall/install.log`

Im having the exact same issue this is my log file
[install.log](https://github.com/archlinux/archinstall/files/12467400/install.log)

Could you share the log file as well under /var/log/archinstall/install.log

Even if you didn't mark it as formatting did you do any other modifications to it? E.g. extend/shrink the size?
Well, I tried again with logs.

1. I had some partitions and a last partiton not to be touched.
2. Chosen manual formatting.
3. Removed all first partitions except the last one.
4. Created partitions for /boot and / with subvolumes.
5. Didn't touch the last partition vda4.

And it wiped vda4 again. Here's logs.

[arch-install.log.zip](https://github.com/archlinux/archinstall/files/12311113/arch-install.log.zip)

The problem seems to be here, it fails to unmount and format vda3.

``` Unmounting: /dev/vda3
Error calling lsblk: lsblk: /dev/vda3: not a block device
{
   "blockdevices": [
   ]
}
```

``` Unmounting: /dev/vda4
Formatting filesystem: /usr/bin/mkfs.fat -F32 /dev/vda1
Formatting filesystem: /usr/bin/mkfs.ext4 -F /dev/vda2
Formatting filesystem: /usr/bin/mkfs.ext4 -F /dev/vda3
Could not format /dev/vda3 with ext4: ['/usr/bin/mkfs.ext4', '-F', '/dev/vda3'] exited with abnormal exit code [1]: mke2fs 1.47.0 (5-Feb-2023)
The file /dev/vda3 does not exist and no size was specified.

Virtualization detected: kvm; is VM: True ```



Resolving patch:
diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py
--- a/archinstall/lib/disk/device_handler.py
+++ b/archinstall/lib/disk/device_handler.py
@@ -242,7 +242,7 @@ def _perform_enc_formatting(
 		info(f'luks2 locking device: {dev_path}')
 		luks_handler.lock()
 
-	def _validate(self, device_mod: DeviceModification):
+	def _validate_partitions(self, partitions: List[PartitionModification]):
 		checks = {
 			# verify that all partitions have a path set (which implies that they have been created)
 			lambda x: x.dev_path is None: ValueError('When formatting, all partitions must have a path set'),
@@ -253,7 +253,7 @@ def _validate(self, device_mod: DeviceModification):
 		}
 
 		for check, exc in checks.items():
-			found = next(filter(check, device_mod.partitions), None)
+			found = next(filter(check, partitions), None)
 			if found is not None:
 				raise exc
 
@@ -266,12 +266,16 @@ def format(
 		Format can be given an overriding path, for instance /dev/null to test
 		the formatting functionality and in essence the support for the given filesystem.
 		"""
-		self._validate(device_mod)
+
+		# don't touch existing partitions
+		filtered_part = [p for p in device_mod.partitions if not p.exists()]
+
+		self._validate_partitions(filtered_part)
 
 		# make sure all devices are unmounted
-		self._umount_all_existing(device_mod)
+		self._umount_all_existing(device_mod.device_path)
 
-		for part_mod in device_mod.partitions:
+		for part_mod in filtered_part:
 			# partition will be encrypted
 			if enc_conf is not None and part_mod in enc_conf.partitions:
 				self._perform_enc_formatting(
@@ -442,10 +446,10 @@ def unlock_luks2_dev(self, dev_path: Path, mapper_name: str, enc_password: str)
 
 		return luks_handler
 
-	def _umount_all_existing(self, modification: DeviceModification):
-		info(f'Unmounting all partitions: {modification.device_path}')
+	def _umount_all_existing(self, device_path: Path):
+		info(f'Unmounting all existing partitions: {device_path}')
 
-		existing_partitions = self._devices[modification.device_path].partition_infos
+		existing_partitions = self._devices[device_path].partition_infos
 
 		for partition in existing_partitions:
 			debug(f'Unmounting: {partition.path}')
@@ -472,7 +476,7 @@ def partition(
 				raise DiskError('Too many partitions on disk, MBR disks can only have 3 primary partitions')
 
 		# make sure all devices are unmounted
-		self._umount_all_existing(modification)
+		self._umount_all_existing(modification.device_path)
 
 		# WARNING: the entire device will be wiped and all data lost
 		if modification.wipe:
@@ -485,13 +489,10 @@ def partition(
 
 		info(f'Creating partitions: {modification.device_path}')
 
-		# TODO sort by delete first
-
-		for part_mod in modification.partitions:
-			# don't touch existing partitions
-			if part_mod.exists():
-				continue
+		# don't touch existing partitions
+		filtered_part = [p for p in modification.partitions if not p.exists()]
 
+		for part_mod in filtered_part:
 			# if the entire disk got nuked then we don't have to delete
 			# any existing partitions anymore because they're all gone already
 			requires_delete = modification.wipe is False
diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py
--- a/archinstall/lib/disk/device_model.py
+++ b/archinstall/lib/disk/device_model.py
@@ -95,6 +95,7 @@ def parse_arg(cls, disk_config: Dict[str, List[Dict[str, Any]]]) -> Optional[Dis
 					length=Size.parse_args(partition['length']),
 					mount_options=partition['mount_options'],
 					mountpoint=Path(partition['mountpoint']) if partition['mountpoint'] else None,
+					dev_path=Path(partition['dev_path']) if partition['dev_path'] else None,
 					type=PartitionType(partition['type']),
 					flags=[PartitionFlag[f] for f in partition.get('flags', [])],
 					btrfs_subvols=SubvolumeModification.parse_args(partition.get('btrfs', [])),
@@ -747,6 +748,7 @@ def json(self) -> Dict[str, Any]:
 			'mountpoint': str(self.mountpoint) if self.mountpoint else None,
 			'mount_options': self.mount_options,
 			'flags': [f.name for f in self.flags],
+			'dev_path': str(self.dev_path) if self.dev_path else None,
 			'btrfs': [vol.__dump__() for vol in self.btrfs_subvols]
 		}
 
diff --git a/archinstall/lib/disk/partitioning_menu.py b/archinstall/lib/disk/partitioning_menu.py
--- a/archinstall/lib/disk/partitioning_menu.py
+++ b/archinstall/lib/disk/partitioning_menu.py
@@ -347,7 +347,7 @@ def manual_partitioning(
 		manual_preset = preset
 
 	menu_list = PartitioningList(prompt, device, manual_preset)
-	partitions = menu_list.run()
+	partitions: List[PartitionModification] = menu_list.run()
 
 	if menu_list.is_last_choice_cancel():
 		return preset


Test patch: