Fixing a Broken GRUB2 Configuration After a Failed Update
A kernel update leaves the system unable to boot into any menu entry — how to regenerate a working GRUB2 configuration from a rescue environment.
A GRUB2 configuration corrupted by an interrupted update — or one that simply references a kernel/initrd pair that no longer exists — needs to be regenerated from a working environment, not hand-edited entry by entry.
Step 1: boot from a live USB/rescue image
Any Linux live environment matching your system’s architecture works for the repair steps below.
Step 2: identify and mount your root partition
lsblk
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot/efi # if using UEFI with a separate ESP
Step 3: chroot into the installed system
for d in dev proc sys; do mount --bind /$d /mnt/$d; done
chroot /mnt /bin/bash
This makes the installed system’s own tools (its specific GRUB version, its specific kernel packages) the ones doing the repair, rather than mismatched tools from the live environment.
Step 4: regenerate the GRUB configuration
grub-mkconfig -o /boot/grub/grub.cfg
On Debian/Ubuntu-based systems, update-grub is a wrapper around the same command.
Step 5: reinstall the GRUB bootloader itself
grub-install /dev/sda
For UEFI systems, this instead targets the EFI System Partition rather than a disk device directly — confirm you’re using the correct invocation for BIOS vs. UEFI boot mode.
Step 6: verify the configuration actually lists valid kernels
grep -A1 "menuentry" /boot/grub/grub.cfg | grep vmlinuz
ls /boot/vmlinuz-*
Confirm every kernel referenced in the generated config file actually exists on disk — a config referencing a removed kernel version means the underlying package state, not GRUB itself, needs cleanup first.
Step 7: clean up orphaned kernel packages if that’s the underlying cause
dpkg --list | grep linux-image # Debian/Ubuntu
rpm -qa | grep kernel # RHEL/Fedora
Remove genuinely orphaned old kernel packages, then regenerate the GRUB config again — this prevents the same broken-reference problem from recurring.
Step 8: exit the chroot and reboot
exit
umount -R /mnt
reboot
Why regenerating beats hand-editing grub.cfg
grub.cfg is an auto-generated file, built from templates in /etc/grub.d/ and the actual installed kernel packages — hand-editing it directly fixes the symptom for exactly one boot, since any future kernel update or grub-mkconfig run overwrites your manual changes. Fixing the underlying package state and regenerating properly is the only change that survives the next update.
Step 9: restore missing dual-boot entries with os-prober
apt install os-prober # if not already present
os-prober
grub-mkconfig -o /boot/grub/grub.cfg
If a dual-boot system’s regenerated grub.cfg only lists Linux kernels and the other operating system’s entry has disappeared, os-prober is the specific component responsible for detecting other installed operating systems and generating their menu entries — some distributions disable it by default for security reasons (a mounted, untrusted partition being scanned), and some GRUB builds simply don’t invoke it unless GRUB_DISABLE_OS_PROBER=false is explicitly set in /etc/default/grub first. Confirming os-prober actually detects the other OS’s partition (os-prober run standalone prints what it found) before regenerating the config isolates whether the problem is detection or generation.
Step 10: don’t skip this on a Secure Boot system
mokutil --sb-state
On a system with UEFI Secure Boot enabled, GRUB is launched through a signed shim binary that verifies GRUB’s own signature before handing off control — reinstalling GRUB (grub-install) on such a system needs to target the correct signed binary path, and a custom or self-compiled kernel needs to be signed and enrolled via mokutil, or Secure Boot will refuse to boot it even after an otherwise-correct GRUB repair. Confirming Secure Boot’s actual state with mokutil --sb-state before troubleshooting further avoids mistaking a signature-verification refusal for a plain GRUB configuration problem — they present similarly at first boot, but need entirely different fixes.
Why grub-mkconfig itself sometimes fails outright rather than producing a bad config
grub-mkconfig isn’t a single monolithic program — it runs each numbered script in /etc/grub.d/ in sequence (10_linux for standard kernel entries, 30_os-prober for other operating systems, and so on) and concatenates their output. A single misbehaving or corrupted script in that directory — one left in a half-updated state by an interrupted package upgrade, or a custom script a previous administrator added and never finished — can make the entire grub-mkconfig run fail or exit early, rather than merely omitting that one script’s own contribution. Running each script individually (sh -x /etc/grub.d/10_linux) isolates exactly which one is actually erroring, which is considerably faster than debugging the full concatenated output when only one specific stage in the pipeline is the real problem.
Related:
- Fixing a Linux System Stuck at ‘grub rescue>’
- Fixing a Kernel Panic on Boot After a Bad Driver or Module Update
Sources: