You are about to cross the release boundary
You just saw the notification that Fedora 41 is available. You click the button, run the command, and three hours later your system won't boot because a third-party repo conflicted with the kernel. Or worse, the upgrade succeeded but your custom kernel parameters vanished. Upgrading Fedora is fast and usually painless, but the preparation determines whether you spend ten minutes waiting or an hour debugging a broken transaction.
A botched upgrade can leave you unable to boot. Run this from a backup VM first if you can.
How the upgrade transaction works
Think of dnf system-upgrade as a moving truck. It packs up your current packages, drives them to the new release version, and unpacks them. If the truck hits a pothole (a dependency conflict), it drops the crates. If you leave junk in the garage (third-party repos or old configs), the movers might get stuck or break something.
The upgrade tool downloads all packages first, then reboots into a special environment to apply them. This two-step process means the download can fail without touching your system, but once the reboot happens, the system is committed. Fedora's release cadence is 6 months. The N-2 release goes EOL when N+1 ships. Plan upgrades on that cycle.
Back up your data
No upgrade guide should skip this. At minimum, back up your home directory. If you use Btrfs, take a snapshot before upgrading. Snapshots are instant and allow you to roll back the entire filesystem if the upgrade breaks something critical.
# Exclude cache to save time and space. Cache rebuilds automatically.
# Use a timestamped directory so you keep multiple backup generations.
rsync -av --exclude='/.cache' /home/$USER/ /mnt/backup/$USER-$(date +%F)/
# Btrfs snapshots are instant and use copy-on-write.
# This creates a read-only point-in-time copy of the root volume.
sudo btrfs subvolume snapshot -r / /snapshots/pre-upgrade-$(date +%F)
Snapshot the system before the upgrade. Future-you will thank you.
Update the current release
The upgrade tool requires the current system to be fully up to date. dnf upgrade --refresh is the normal weekly maintenance command. dnf system-upgrade is for crossing major Fedora releases. They are different commands. Don't conflate them.
# --refresh forces dnf to check for new metadata even if cached data is fresh.
# This ensures you are upgrading from the absolute latest state of the current release.
sudo dnf upgrade --refresh
If a kernel update is included, you must reboot. Upgrading over an old kernel can cause module mismatches during the transaction.
# A kernel update requires a reboot to take effect.
# Upgrading over an old kernel can cause module mismatches during the transaction.
sudo reboot
Reboot before you debug. Half the time the symptom is gone.
Verify disk space
The upgrade downloads several gigabytes of packages. Verify you have at least 10 GB free on the root partition. The download fails silently if the disk fills up mid-transfer, leaving a corrupted cache.
# Check the root filesystem. The upgrade needs space for downloads and temporary files.
df -h /
If space is tight, clean old package caches and unused kernels. Old kernels accumulate and consume significant space.
# Remove the package cache to reclaim space immediately.
sudo dnf clean all
# Remove old kernels, keeping only the current and the latest installed one.
# This prevents the root partition from filling up with unused kernel images.
sudo dnf remove $(dnf repoquery --installonly --latest-limit=-2 -q)
Clean the cache before the download. A full disk kills the transaction.
Manage third-party repositories
Third-party repos that do not support the new Fedora release can block or break the upgrade. The upgrade tool checks all enabled repositories. If a repo lacks packages for the target release, the transaction fails.
# List all enabled repositories to identify third-party sources.
dnf repolist
# Disable a repo that does not yet provide packages for the target release.
# The upgrade will skip this repo and continue with the official Fedora repositories.
sudo dnf config-manager --set-disabled <repo-id>
Check the repository website before disabling. Some repos like RPM Fusion provide packages for the new release immediately. Others lag behind. If you disable a repo, re-enable it after the upgrade completes and verify the repo has packages for the new release.
Disable the third-party repo before the download. A missing package stops the whole train.
Apply firmware updates
Firmware updates can affect hardware compatibility. Apply any pending firmware updates before the OS upgrade. Firmware updates often require a reboot and can resolve issues that look like OS bugs.
# Refresh the firmware metadata from the upstream database.
sudo fwupdmgr refresh
# Apply any pending firmware updates before the OS upgrade.
# Firmware updates often require a reboot and can affect hardware compatibility.
sudo fwupdmgr update
Apply firmware updates before the OS upgrade. Hardware bugs can masquerade as OS bugs.
Review custom kernel and dracut configuration
If you have custom files in /etc/modprobe.d/, /etc/dracut.conf.d/, or /etc/sysctl.d/, confirm they are still valid for the new release. Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/.
Some hardware quirks are fixed upstream and old workarounds can cause boot failures. If you added a custom hook to /etc/dracut.conf.d/, verify it is compatible with the new dracut version. Dracut changes frequently between releases.
Check /etc/ before you reboot. Manual file edits drift, snapshots stay.
Execute the upgrade
Once preparation is complete, use the official dnf system-upgrade plugin. The download step verifies dependencies and allows you to cancel before the system changes.
# Install the plugin if it is not already present.
sudo dnf install dnf-plugin-system-upgrade
# Download all packages for the target release without applying them yet.
# This step verifies dependencies and allows you to cancel before the system changes.
sudo dnf system-upgrade download --releasever=41
# Reboot into the upgrade environment.
# The system will apply the downloaded packages and reboot again automatically.
sudo dnf system-upgrade reboot
Run the download first. Verify the transaction before you commit.
Verify the new system
After the second reboot, confirm the new version and clean up old packages. Package versions drift until you align them with the new release repositories.
# Confirm the system booted into the new release.
cat /etc/fedora-release
# Sync the system state with the new release repositories.
# This resolves any package versions that drifted during the upgrade.
sudo dnf distro-sync
# Remove packages that were dependencies of the old release but are no longer needed.
sudo dnf autoremove
Run distro-sync after the upgrade. Package versions drift until you align them.
Common pitfalls and error messages
The dnf system-upgrade download command will refuse to proceed and print Error: Transaction test error: package python3-3.12.x conflicts with python3-3.13.y. The conflict is intentional. Read the next paragraph before forcing.
If you see GPG check FAILED, the repository key has likely rotated. Check the repository documentation for the new key import command. Do not disable GPG checks.
If the upgrade hangs, check the journal. journalctl -xeu dnf-system-upgrade.service shows the exact step where the process stalled. SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux.
If you see [FAILED] Failed to start NetworkManager.service during boot, your network configuration probably references a missing interface name. Interface names can change between releases if the naming scheme updates.
Run journalctl first. Read the actual error before guessing.
When to use system-upgrade versus alternatives
Use dnf system-upgrade when you want to keep your configuration and packages intact across a release boundary. Use a fresh install when your system has accumulated years of customizations and you suspect configuration drift. Use Silverblue when you want a known-good base image you can always roll back to. Use dnf upgrade --refresh when you are staying on the same release and just want the latest security patches.