A kernel update that leaves Fedora unable to boot is not a reinstall job. Fedora keeps the previous kernels on disk, and every one of them still has a working boot entry. The only hard part is reaching the GRUB menu, which Workstation hides by default.
This guide covers what to do when Fedora won’t boot after an update. You boot the older kernel from GRUB, find out what broke, repair the new kernel, and make Fedora keep a known-good kernel as the default until you are ready to move on. We broke a kernel on purpose, twice, to get the real error screens: once by removing its initramfs (what an interrupted update or a full /boot leaves behind) and once with a forced kernel panic.
Verified October 2026 on Fedora 45 Workstation, Secure Boot on, SELinux enforcing.
Why the GRUB menu is hidden, and when it comes back
Fedora Workstation sets menu_auto_hide=1 in the GRUB environment block. GRUB then waits one second with the menu hidden and boots the default entry. Check your machine:
sudo grub2-editenv list
Our Workstation install showed the auto-hide flag and the two boot flags that control it:
saved_entry=c2d65377f09a45b99c54afec373af9f4-7.2.8-300.fc45.x86_64
menu_auto_hide=1
boot_success=1
boot_indeterminate=2
The hiding is conditional. /etc/grub.d/10_reset_boot_success only allows it when the previous boot set boot_success=1, and it resets the flag to 0 on every boot. A systemd user timer, grub-boot-success.timer, sets it back to 1 after a user session has run for 2 minutes. A boot that never reaches that point leaves the flag at 0, so the next boot shows the menu with the normal 5 second GRUB_TIMEOUT countdown. The one exception is the reboot that applies an offline update: grub-boot-indeterminate.service runs before system-update-pre.target and marks that boot as indeterminate, which still allows the hidden menu.
One detail changes how far that safety net reaches. On Fedora 45 the GDM login screen runs its own user manager as gdm-greeter, and that session starts the same timer. The journal on our test box shows it firing two minutes after boot with nobody logged in:
sudo journalctl -b --no-pager -o short-iso | grep -E "systemd\[923\].*grub-boot-success.service" | tail -3
PID 923 is the greeter’s user manager:
2026-10-04T14:13:38+03:00 kern-lab01 systemd[923]: Starting grub-boot-success.service - Mark boot as successful...
2026-10-04T14:13:39+03:00 kern-lab01 systemd[923]: Finished grub-boot-success.service - Mark boot as successful.
The failure mode follows from that. If the new kernel reaches the login screen and breaks only after you sign in (a GPU driver that crashes GNOME, for example), the boot already counts as successful, and the menu stays hidden next time. Step 1 shows how to bring it back in that case.
Step 1: Get to the GRUB menu
There are three ways in, depending on how far the broken boot got.
The new kernel fails before the login screen
There are two ways this goes, and we triggered both.
When GRUB cannot load the kernel’s files, it never gets as far as Linux. We removed the initramfs of the newest kernel (7.2.8) and rebooted. GRUB could not load the entry, printed the error and “Failed to boot both default and fallback entries”, and waited for a key:

Press a key (twice on our box) and GRUB drops into its menu, in the same session and with no countdown:

When the kernel starts but dies, you get a panic instead. We gave 7.2.8 a broken init= argument to force one, and Fedora 45 showed its panic screen with a QR code of the kernel log:

Fedora sets kernel.panic = 0, so a panicked kernel sits on that screen until you hold the power button or reset the machine. That boot never set boot_success, so the next start shows the menu, but only for the 5 second countdown:

Press an arrow key before the counter runs out. That stops the countdown. If you miss it, GRUB boots the broken kernel again, which is exactly what happened on our first try.
The new kernel reaches the login screen, then misbehaves
This is the case where the menu stays hidden, because the login screen marked the boot successful after two minutes. If you can still get a shell (a text console with Ctrl+Alt+F3, SSH, or the older kernel itself), ask GRUB to show the menu on the next boot only:
sudo grub2-editenv - set menu_show_once=1
/etc/grub.d/12_menu_auto_hide turns that flag into a visible menu with a 60 second countdown, then clears the flag. After our reboot the menu waited with the counter running:

The flag was gone on the next grub2-editenv list, so the following boot hides the menu again. To show the menu on every boot instead, remove the auto-hide flag with sudo grub2-editenv - unset menu_auto_hide. GRUB then uses the plain 5 second timeout each time.
No shell at all? The Hidden GRUB menu change documents holding Shift, or pressing Esc or F8, while GRUB starts. The window is the one second of hidden timeout. On our VM, pressing Esc from power-on opened the UEFI firmware setup instead, because the firmware catches the key first. Wait until the firmware logo is gone, then press the key. The fallback is a forced power-off within two minutes of the login screen appearing, before the boot is marked successful. Never cut power while the screen says updates are being installed: that is an offline update applying, and interrupting it can leave the system half-updated.
Step 2: Boot the previous kernel
The menu lists every installed kernel, newest first, plus a rescue entry. Move down one line to the previous kernel and press Enter. Any arrow key also stops a running countdown:

The rescue entry (0-rescue-...) is the install-time kernel with a generic (non-hostonly) initramfs. Use it only when none of the regular kernels boot. Once dnf has trimmed that kernel’s modules from /usr/lib/modules, the rescue entry can still start but can’t load any module that isn’t in its initramfs, so don’t count on it as your only fallback.
Once you are logged in, confirm which kernel is running and what GRUB will boot next time:
uname -r; sudo grub2-editenv list
The older kernel is running, but saved_entry still points at the broken one:
7.2.7-300.fc45.x86_64
saved_entry=c2d65377f09a45b99c54afec373af9f4-7.2.8-300.fc45.x86_64
menu_auto_hide=1
boot_success=0
boot_indeterminate=0
Do not reboot yet. Without a fix or a new default, the next boot tries 7.2.8 again.
Step 3: Find out what broke
Start with the boot list. A boot that died inside GRUB never reached the kernel, so it leaves no journal at all:
journalctl --list-boots --no-pager | tail -3
Boot -1 is the last good session, the one that installed the update. The failed 7.2.8 attempt is missing between it and the current boot:
-2 84e61b2733f14c7e899a44492313c4c5 Sun 2026-10-04 13:39:38 EAT Sun 2026-10-04 13:40:04 EAT
-1 5568b5c6483547438e674367468cf6d0 Sun 2026-10-04 13:40:13 EAT Sun 2026-10-04 13:56:26 EAT
0 ab57845bc80b49ffad542bcdfa027733 Sun 2026-10-04 13:58:27 EAT Sun 2026-10-04 13:58:40 EAT
Check which initramfs images exist and which kernel GRUB boots by default:
ls /boot/initramfs-*; sudo grubby --default-kernel
The 7.2.8 initramfs is missing, and 7.2.8 is still the default:
/boot/initramfs-0-rescue-c2d65377f09a45b99c54afec373af9f4.img
/boot/initramfs-7.2.0-61.fc45.x86_64.img
/boot/initramfs-7.2.7-300.fc45.x86_64.img
/boot/vmlinuz-7.2.8-300.fc45.x86_64
A missing boot does not prove the failure was in GRUB. Our two panicked 7.2.8 boots were missing from --list-boots too, because the kernel died before journald could write to disk. When a bad boot does show up, its kernel messages are in journalctl -b -1 -k. That is where failures later in boot, such as an NVIDIA module not built for the new kernel, leave their trace. A missing initramfs usually means an update was cut off or /boot filled up. On Workstation, /boot is a separate 2 GB ext4 partition, so check df -h /boot before you rebuild anything.
Step 4: Repair the broken kernel
Reinstalling the kernel package runs the same kernel-install hooks as the original update, and those rebuild the initramfs:
sudo dnf -y reinstall kernel-core-7.2.8-300.fc45 2>&1 | tail -6
The transaction finished, with one warning worth reading:
[2/4] Prepare transaction 100% | 7.0 B/s | 2.0 B | 00m00s
[3/4] Reinstalling kernel-core-0:7.2.8- 100% | 6.3 MiB/s | 30.7 MiB | 00m05s
[4/4] Removing kernel-core-0:7.2.8-300. 100% | 0.0 B/s | 17.0 B | 00m41s
Warning: Pending offline transaction has been invalidated.
To reschedule, run: dnf5daemon-server
Complete!
An offline update was queued for the next reboot, and the manual transaction cancelled it. sudo dnf offline status showed it came from dnf5daemon-server, the backend GNOME Software uses on Workstation. That is the safe outcome here, since you don’t want an untested batch landing on the next restart. Let GNOME Software queue it again once the system is stable.
The reinstall only works while that exact kernel build is still in an enabled repo. Fedora drops superseded kernels from updates. Asking dnf to reinstall our install-time 7.2.0 kernel, which no repo carries any more, failed with Packages for argument 'kernel-core-7.2.0-61.fc45' installed, but not available.
Check that the image is back and readable:
ls -l /boot/initramfs-7.2.8-300.fc45.x86_64.img; sudo lsinitrd /boot/initramfs-7.2.8-300.fc45.x86_64.img | head -3
A 52 MB image, and lsinitrd can open it:
-rw-------. 1 root root 53605122 Oct 4 13:59 /boot/initramfs-7.2.8-300.fc45.x86_64.img
Image: /boot/initramfs-7.2.8-300.fc45.x86_64.img: 52M
========================================================================
Early CPIO image
dracut rebuilds the initramfs from the files already installed, so it works even when the package is gone from the repos:
sudo dracut --force --kver 7.2.8-300.fc45.x86_64; echo dracut_rc=$?; ls -l /boot/initramfs-7.2.8-300.fc45.x86_64.img
It exited cleanly and wrote a fresh image:
dracut_rc=0
-rw-------. 1 root root 53603950 Oct 4 14:00 /boot/initramfs-7.2.8-300.fc45.x86_64.img
After either repair, 7.2.8 booted normally on the next restart. A missing initramfs is fixable this way. A kernel that boots but panics in a driver is not, and that is when you keep the older kernel for a while.
Step 5: Keep the older kernel as the default
grubby sets the default entry by kernel path:
sudo grubby --set-default /boot/vmlinuz-7.2.7-300.fc45.x86_64
It confirms the entry it picked:
The default is /boot/loader/entries/c2d65377f09a45b99c54afec373af9f4-7.2.7-300.fc45.x86_64.conf with index 1 and kernel /boot/vmlinuz-7.2.7-300.fc45.x86_64
That choice does not survive the next kernel update. On our install, /etc/sysconfig/kernel had UPDATEDEFAULT=yes, which makes every newly installed kernel the default. We reinstalled 7.2.8 with the 7.2.7 default in place, and sudo grubby --default-kernel printed /boot/vmlinuz-7.2.8-300.fc45.x86_64 again.
Turn that off while you wait for a fixed kernel:
sudo sed -i "s/^UPDATEDEFAULT=yes/UPDATEDEFAULT=no/" /etc/sysconfig/kernel
With UPDATEDEFAULT=no, we set 7.2.7 as default again and repeated the reinstall. The default stayed put:

New kernels still install and still appear in the menu with this setting. They just stop taking over the default. Switch it back to yes once a fixed kernel is out, or new kernels will never become the default again. The same setting keeps Windows as the default entry on a machine set up with the Fedora and Windows 11 dual boot guide. The grubby guide covers kernel arguments and the other entry options.
Step 6: Keep enough kernels installed
dnf keeps three kernels by default (installonly_limit = 3). Each update past that removes the oldest one, except the kernel you are running, which dnf never removes. The risk is the setup from Step 5: you pin a good kernel as the default but keep booting newer ones to test them. With the default limit, the next kernel update makes the pinned one the oldest on disk, and the one after that removes it. Preview what dnf would remove at a lower limit:
sudo dnf remove --oldinstallonly --setopt=installonly_limit=2 --assumeno 2>&1 | grep -E "^ kernel|Removing|Transaction Summary|Nothing|Problem|Error" | head -12
The oldest kernel goes first:
Removing:
kernel x86_64 0:7.2.0-61.fc45 401d2d4aafb94a2f9a713d221acd0ad5 0.0 B
kernel-core x86_64 0:7.2.0-61.fc45 401d2d4aafb94a2f9a713d221acd0ad5 101.6 MiB
kernel-modules x86_64 0:7.2.0-61.fc45 401d2d4aafb94a2f9a713d221acd0ad5 100.6 MiB
kernel-modules-core x86_64 0:7.2.0-61.fc45 401d2d4aafb94a2f9a713d221acd0ad5 73.9 MiB
kernel-modules-extra x86_64 0:7.2.0-61.fc45 401d2d4aafb94a2f9a713d221acd0ad5 3.9 MiB
Transaction Summary:
Removing: 5 packages
A version lock does not protect it. We ran sudo dnf versionlock add kernel-core-7.2.0-61.fc45, repeated the preview, and got the identical removal list. versionlock controls which versions dnf may install, not which installed kernels it trims. Remove the lock again with sudo dnf versionlock delete kernel-core.
What works is a higher limit. dnf5 writes it to /etc/dnf/dnf.conf:
sudo dnf config-manager setopt installonly_limit=5
Check that dnf picked it up, and where the setting landed:
dnf --dump-main-config 2>/dev/null | grep ^installonly_limit; sudo grep -rH installonly /etc/dnf/
The limit is live and stored in the main config file:
installonly_limit = 5
/etc/dnf/dnf.conf:installonly_limit=5
The removal preview now finds nothing to trim:
sudo dnf remove --oldinstallonly --assumeno 2>&1 | tail -3
dnf answers in three words:
Nothing to do.
Each Fedora 45 kernel took 84 MB in /boot on our box (kernel, initramfs and maps) plus 170 MB of modules under /usr/lib/modules. Five of them fit on the 2 GB /boot partition, which had 550 MB in use with three kernels and the rescue image. A Btrfs snapshot covers the rest of the system: the Snapper and grub-btrfs setup adds bootable snapshots to the same GRUB menu.
Recovery checklist for the next kernel update
Run through this list once, while the machine still boots, so a bad kernel costs you a reboot and not an afternoon. It belongs next to the rest of the post-install setup on any new Fedora machine:
rpm -q kernel-corelists at least two kernels, and you know which one last worked.installonly_limitis high enough that a pinned kernel survives the updates you plan to test (5 leaves room for several test kernels).df -h /bootshows room for another kernel and initramfs.- You know how to reach the menu:
sudo grub2-editenv - set menu_show_once=1before a risky reboot. - If you rely on out-of-tree modules (NVIDIA, VirtualBox), they are built for the new kernel before you reboot. The NVIDIA driver guide shows the
modinfo -kcheck for this. UPDATEDEFAULTin/etc/sysconfig/kernelis back toyesonce you no longer need to pin.
Release upgrades bring a new kernel too. Run the same checks before the Fedora 44 to 45 upgrade, and keep the old release’s kernel installed until the new one has booted a few times.