Change:
The script is apparently trying to stop and start changed .mount units, presumably to cause a ? If that happens the script fails and the new configuration is not activated. Worse, the system is left in a broken state with some of the stopped (as part of the switch) units never restarted. Steps to reproduce the behavior: the value of , for example from to . The unit should probably not be stopped and the switch should succeed. If using remotely also the SSH connection drops. NixOS version: 23.05.1194. (Stoat) The filesystem entry is: cc:
I just ran into this error myself. I am unsure of which configuration change caused this. But I was changing config and I think was saying some setting conflicts with my , which was at . So I updated to and then flashed me this error: before giving me a black screen and send me to the login prompt.
were you ever able to fix your issue?
No fix, I'm pretty sure changing the unit will still trigger a stop.
Unfortunately, you are correct. I do have a fix in the pipeline though. improves the handling of mount units () and I plan to adapt this to fstab mounts as well (). This is currently being blocked by the fstab parser not having any tests but I plan on writing them. Will keep this issue in mind.
Now that I look at the code again… it already looks correct. Can someone with this issue post a diff of their fstab? Something like should do.

Discussion:
and the actions to switch to the new system are calculated. This process takes two data sources into account: `/etc/fstab` and the current systemd status. Mounts and swaps are read from `/etc/fstab` and the corresponding actions are <del> generated. If a new mount is added, for example, the proper `.mount` unit is marked to be started. The current systemd state is inspected, the difference </del> <ins> generated. If the options of a mount are modified, for example, the proper `.mount` unit is reloaded (or restarted if anything else changed and it's neither the root mount or the nix store). The current systemd state is inspected, the difference </ins> between the current system and the desired configuration is calculated and actions are generated to get to this state. There are a lot of nuances that can be controlled by the units which are explained here.

if (!defined($action) || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) { print STDERR <<"EOF"; <del> Usage: $0 [switch|boot|test] </del> <ins> Usage: $0 [switch|boot|test|dry-activate] </ins> switch:       make the configuration the boot default and activate now boot:         make the configuration the boot default

# Filesystem entry disappeared, so unmount it. $units_to_stop{$unit} = 1; } elsif ($cur->{fsType} ne $new->{fsType} || $cur->{device} ne $new->{device}) { <del> # Filesystem type or device changed, so unmount and mount it. $units_to_stop{$unit} = 1; $units_to_start{$unit} = 1; record_unit($start_list_file, $unit); </del> <ins> if ($mount_point eq '/' or $mount_point eq '/nix') { if ($cur->{options} ne $new->{options}) { # Mount options changed, so remount it. $units_to_reload{$unit} = 1; record_unit($reload_list_file, $unit); } else { # Don't unmount / or /nix if the device changed $units_to_skip{$unit} = 1; } } else { # Filesystem type or device changed, so unmount and mount it. $units_to_restart{$unit} = 1; record_unit($restart_list_file, $unit); } </ins> } elsif ($cur->{options} ne $new->{options}) { # Mount options changes, so remount it. $units_to_reload{$unit} = 1;

''); specialisation = rec { <ins> brokenInitInterface.configuration.config.system.extraSystemBuilderCmds = '' echo "systemd 0" > $out/init-interface-version ''; modifiedSystemConf.configuration.systemd.extraConfig = '' # Hello world! ''; addedMount.configuration.virtualisation.fileSystems."/test" = { device = "tmpfs"; fsType = "tmpfs"; }; addedMountOptsModified.configuration = { imports = [ addedMount.configuration ]; virtualisation.fileSystems."/test".options = [ "x-test" ]; }; addedMountDevModified.configuration = { imports = [ addedMountOptsModified.configuration ]; virtualisation.fileSystems."/test".device = lib.mkForce "ramfs"; }; storeMountModified.configuration = { virtualisation.fileSystems."/".device = lib.mkForce "auto"; }; swap.configuration.swapDevices = lib.mkVMOverride [ { device = "/swapfile"; size = 1; } ]; </ins> simpleService.configuration = { systemd.services.test = { wantedBy = [ "multi-user.target" ];

# test and dry-activate actions are tested further down below <ins> # invalid action fails the script switch_to_specialisation("${machine}", "", action="broken-action", fail=True) # no action fails the script assert "Usage:" in machine.fail("${machine}/bin/switch-to-configuration 2>&1") with subtest("init interface version"): # Do not try to switch to an invalid init interface version assert "incompatible" in switch_to_specialisation("${machine}", "brokenInitInterface", fail=True) with subtest("systemd restarts"): # systemd is restarted when its system.conf changes out = switch_to_specialisation("${machine}", "modifiedSystemConf") assert_contains(out, "restarting systemd...") with subtest("continuing from an aborted switch"): # An aborted switch will write into a file what it tried to start # and a second switch should continue from this machine.succeed("echo dbus.service > /run/nixos/start-list") out = switch_to_specialisation("${machine}", "modifiedSystemConf") assert_contains(out, "starting the following units: dbus.servicen") with subtest("fstab mounts"): switch_to_specialisation("${machine}", "") # add a mountpoint out = switch_to_specialisation("${machine}", "addedMount") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_contains(out, "the following new units were started: test.mountn") # modify the mountpoint's options out = switch_to_specialisation("${machine}", "addedMountOptsModified") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_contains(out, "reloading the following units: test.mountn") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") # modify the device out = switch_to_specialisation("${machine}", "addedMountDevModified") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_lacks(out, "reloading the following units:") assert_contains(out, "nrestarting the following units: test.mountn") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") # modify both out = switch_to_specialisation("${machine}", "addedMount") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_lacks(out, "reloading the following units:") assert_contains(out, "nrestarting the following units: test.mountn") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") # remove the mount out = switch_to_specialisation("${machine}", "") assert_contains(out, "stopping the following units: test.mountn") assert_lacks(out, "NOT restarting the following changed units:") assert_contains(out, "reloading the following units: dbus.servicen") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") # change something about the / mount out = switch_to_specialisation("${machine}", "storeMountModified") assert_lacks(out, "stopping the following units:") assert_contains(out, "NOT restarting the following changed units: -.mount") assert_contains(out, "reloading the following units: dbus.servicen") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") with subtest("swaps"): switch_to_specialisation("${machine}", "") # add a swap out = switch_to_specialisation("${machine}", "swap") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_contains(out, "reloading the following units: dbus.servicen") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_contains(out, "the following new units were started: swapfile.swap") # remove it out = switch_to_specialisation("${machine}", "") assert_contains(out, "stopping swap device: /swapfile") assert_lacks(out, "stopping the following units:") assert_lacks(out, "NOT restarting the following changed units:") assert_contains(out, "reloading the following units: dbus.servicen") assert_lacks(out, "nrestarting the following units:") assert_lacks(out, "nstarting the following units:") assert_lacks(out, "the following new units were started:") </ins> with subtest("services"): switch_to_specialisation("${machine}", "") # Nothing happens when nothing is changed