The upgrade scenario
You just finished your weekly package update and noticed Fedora 41 is available. You want to move forward, but you remember hearing that crossing major releases requires a different approach. You run the standard upgrade command, it refuses to work, and you are left wondering why the package manager suddenly changed the rules. This is normal. Fedora separates routine package updates from full release transitions for a reason. The standard command only touches software within the current release. It never changes the base release version. When you cross from 40 to 41, you are replacing the entire package set, including the kernel, core libraries, and system services. The dnf system-upgrade plugin handles this by downloading all new packages first, verifying the transaction, and then rebooting into a special upgrade environment. Think of it like replacing the foundation of a house while the family is still inside. You gather all the new materials, check that they fit, and then swap everything out during a planned downtime. The package manager does the heavy lifting so you do not have to manually resolve hundreds of dependencies.
Run a full system backup before starting. A failed transaction can leave critical binaries in an inconsistent state.
What the system-upgrade command actually works
The upgrade process happens in two distinct phases. The first phase downloads and verifies. The second phase executes during boot. This separation exists because package managers cannot safely replace files that are currently in use. If dnf tried to overwrite libsystemd.so while systemd was running, the system would crash immediately. Instead, the plugin stages the entire transaction in the dnf cache. It calculates every dependency, checks for conflicts, and prepares a list of files to replace. Once verification passes, it drops a control file into /var/lib/dnf/system-upgrade. The initramfs reads this file on the next boot, mounts the root filesystem read-only, and runs the actual package swap before the normal system services start. This means the upgrade happens in a controlled environment where no user processes are holding files open.
The plugin also handles kernel and initramfs regeneration automatically. New kernels get installed, GRUB configuration updates, and the boot loader points to the correct entry. You do not need to run dracut or grub2-mkconfig manually. The transaction rolls back automatically if a package fails to install. This safety net is why the download phase takes longer than a normal update. Dnf is building a complete snapshot of the target system before it touches your disk.
Verify your disk space before proceeding. The cache will temporarily hold two full system installations.
Preparing the current system
A partially updated Fedora 40 system will cause dependency conflicts during the transition. You must start from a clean, fully patched state. Run the standard refresh and upgrade cycle first.
sudo dnf upgrade --refresh
# --refresh forces dnf to fetch fresh metadata from the mirrors
# This ensures you are starting from a known-good Fedora 40 state
# The command resolves all pending updates within the current release
Reboot after the update completes. Half the time, pending kernel or library changes require a clean slate before the next major step.
Once you are back at a prompt, confirm the system-upgrade plugin is available. Fedora Workstation and Server include it by default, but minimal spins sometimes leave it out.
sudo dnf install dnf-plugin-system-upgrade
# The plugin adds the system-upgrade subcommand to dnf
# It handles the two-phase download and reboot process
# Existing installations will simply confirm the package is already present
Check your third-party repositories. RPM Fusion, Flatpak overrides, or custom YUM repos might not have Fedora 41 packages ready yet. Dnf will refuse to proceed if a repository lacks metadata for the target release. Disable problematic repos temporarily during the download phase.
sudo dnf system-upgrade download --releasever=41 --disablerepo=rpmfusion-free-updates-testing
# --releasever=41 tells dnf to switch metadata to the 41 repository
# --disablerepo prevents incomplete third-party repos from breaking the transaction
# The download phase verifies dependencies before touching disk
Watch the transaction summary carefully. If dnf lists packages to remove that you rely on, abort with Ctrl+C. Investigate the conflict before proceeding. A botched upgrade can leave you unable to boot. Run this from a backup VM first if you can.
Trust the package manager. Manual file edits drift, snapshots stay.
Running the two-phase upgrade
After the download finishes successfully, trigger the reboot phase. This command schedules the upgrade to run during the next boot sequence.
sudo dnf system-upgrade reboot
# This drops a transaction file into /var/lib/dnf/system-upgrade
# The initramfs reads it on boot and runs the actual package swap
# The system will automatically restart without further user input
The screen will go black, then show dnf progress bars. Do not interrupt the power. The system is replacing core binaries and updating GRUB. Wait for the login prompt to return. The process typically takes between ten and twenty minutes depending on your disk speed and network latency. If you are on a slow connection, the download phase will dominate the timeline. The reboot phase is usually fast because it only writes files to disk and regenerates the boot environment.
If the boot menu is gone, GRUB rescue is your friend, not your enemy.
Verifying the new release
You need to confirm the transition actually completed and that the new kernel is active. Check the release version file and the running kernel.
cat /etc/fedora-release
# This file is managed by the fedora-release package
# It should now read Fedora release 41 (Thirty One)
# Older release files are removed during the transaction
uname -r
# Confirms the kernel version matches the 41 series
# Older 40 kernels remain on disk until you clean them up
# The bootloader automatically selects the newest kernel by default
Run journalctl -xe to scan for startup errors. The x flag adds explanatory context and the e flag jumps to the end. Most service failures show up here within the first few minutes of boot. Look for [FAILED] markers or dependency loops. If a service failed to start, check its specific unit with systemctl status <unit>. The status command shows recent log lines AND state in one view. Always check status before restart.
journalctl -xeu NetworkManager.service
# Filters logs to a specific unit for faster troubleshooting
# The -u flag isolates the service output from the full journal
# Use this when a single service is causing boot delays
Run journalctl first. Read the actual error before guessing.
Common pitfalls and error messages
The most common failure is a repository mismatch. If you added third-party repos like RPM Fusion or custom build servers, they might not have Fedora 41 packages ready yet. Dnf 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. Disable the problematic repo temporarily with --disablerepo=repo-name during the download phase.
Another frequent issue is leftover configuration drift. Files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. If you manually patched a system file in /usr/lib/, the upgrade will overwrite it and dnf will flag it as a modified file. Restore the original or move your changes to /etc/ before upgrading.
SELinux denials sometimes appear during the transition. They show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. The upgrade process relabels files automatically, but custom mounts or non-standard home directories can trigger alerts. Fedora's release cadence is 6 months. The N-2 release goes EOL when N+1 ships. Plan upgrades on that cycle.
Snapshot the system before the upgrade. Future-you will thank you.
Post-upgrade cleanup
The upgrade leaves behind old kernels, cached packages, and orphaned dependencies. Clean them up to reclaim disk space and reduce boot menu clutter.
sudo dnf autoremove
# Removes packages that were installed as dependencies but are no longer needed
# This catches leftover kernel modules and development headers
# Review the list carefully before confirming
sudo dnf clean all
# Clears the dnf cache directory and removes staged transaction files
# Frees several gigabytes of temporary download data
# Safe to run immediately after a successful upgrade
Reboot one final time. This ensures the system boots with a clean initramfs and removes any lingering upgrade hooks from memory.
Reboot before you debug. Half the time the symptom is gone.
Choosing your upgrade path
Use dnf system-upgrade when you want a straightforward in-place transition from one supported release to the next. Use a clean installation when your system has accumulated years of configuration drift or broken third-party packages. Use dnf system-upgrade download --releasever=42 when you want to skip Fedora 41 entirely and jump straight to the next major release. Stay on the current release when you are running production services that require stability over new features. Use Silverblue when you want a known-good base image you can always roll back to. Use Workstation when you need to install kernel modules or low-level driver patches. Use Server when you are running services and not a desktop. Stay on the upstream Workstation if you only deviate from the defaults occasionally.
Pick the path that matches your tolerance for manual intervention.