The upgrade stops at a black screen
You run the upgrade command on a Friday evening. The machine reboots, sits at a blank screen for twenty minutes, then drops you into a rescue shell. The transition failed because a third-party repository served a stale package, or your root partition ran out of space during the download phase. A botched release transition can leave you unable to boot. Run through this checklist from a backup VM or a live USB first if you can.
What the transition actually does
dnf system-upgrade does not stream packages directly into your running system. It downloads the entire new release into a temporary cache, verifies the transaction, and schedules a one-time boot target that applies the changes before the init system starts. Think of it like replacing the engine of a car while it is parked in a garage. The car stays on the lift until every bolt is tightened and the fluids are filled. If you skip the prep work, the lift drops with half the work done.
The tool stages everything offline. Your current release continues to run normally until you explicitly trigger the reboot phase. This design prevents partial upgrades and keeps your system in a known state. It also means you need enough disk space to hold both the current packages and the new ones simultaneously.
Prepare the current system
A clean baseline prevents dependency conflicts during the staging phase. Run a full metadata refresh and apply every available patch for your current release. The upgrade tool requires a fully patched system before it will proceed.
sudo dnf upgrade --refresh -y
# --refresh forces dnf to ignore cached metadata and fetch fresh repo data
# -y automatically confirms the transaction so you can walk away
sudo reboot
# Reboot applies kernel updates and clears stale module caches
Check your root partition before proceeding. The download phase stores every package for the new release in /var/lib/dnf/system-upgrade/. You need at least five gigabytes free on the root partition. Large desktop environments with full development toolchains often require eight to ten gigabytes.
df -h /
# -h formats sizes in human-readable units
# Look at the "Avail" column. Anything under 5G is a hard stop.
Back up home directories, configuration files, and databases. The upgrade process preserves user data by design, but storage controllers fail and power interruptions happen. Copy your critical files to an external drive or a remote server before touching the package manager.
rsync -av --progress ~/ /mnt/backup/home-$(date +%F)/
# -a preserves permissions, timestamps, and symlinks
# -v shows progress so you can verify the transfer completes
# The date stamp keeps each backup isolated and recoverable
Review your repository list. Third-party and Copr repositories often lag behind Fedora's release schedule. If a repository has not yet built packages for the target release, dnf will try to mix old and new packages. That creates unresolvable dependency chains.
dnf repolist
# Lists every enabled repository and their current release version
# Look for repos that still point to your current release number
Disable any repository that is not release-agnostic. You can re-enable them after the upgrade once the maintainer publishes updated packages.
sudo dnf config-manager --set-disabled <repo-id>
# --set-disabled modifies the repo configuration in /etc/yum.repos.d/
# This prevents dnf from pulling mismatched packages during staging
Convention aside: dnf upgrade --refresh is the normal weekly maintenance command. dnf system-upgrade is for crossing major Fedora releases. They are different commands. Do not conflate them.
Snapshot the system before the upgrade. Future-you will thank you.
Stage the new release
Install the system-upgrade plugin if it is not already present. Fedora Workstation and Server include it by default, but minimal installations sometimes strip it out.
sudo dnf install dnf-plugin-system-upgrade
# Ensures the system-upgrade command is available in your PATH
# The plugin adds the download and reboot subcommands to dnf
Download the new release packages. Replace <next-version> with the target release number, such as 41 or 42. This step does not reboot the machine. It only populates the upgrade cache and runs a dependency check.
sudo dnf system-upgrade download --releasever=<next-version>
# --releasever tells dnf which Fedora release to target
# The download phase verifies every package signature and dependency
If this step lists unresolvable dependencies or blockers, address them before proceeding. The output will show exactly which packages conflict. Do not force the transaction. A forced transaction breaks the next boot.
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.
Check for out-of-tree kernel modules. Drivers like NVIDIA via akmod-nvidia or VirtualBox rely on kernel headers to rebuild against the new kernel. Confirm your akmod packages are installed and configured.
rpm -qa | grep akmod
# Lists all akmod packages currently installed on the system
# If missing, install them before staging to ensure headers are available
Convention aside: Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. The upgrade process will overwrite /usr/lib/ files without warning.
Read the dependency tree before forcing. A forced transaction breaks the next boot.
Execute the reboot
Once the download completes successfully, trigger the upgrade phase. This command schedules a one-time boot target. The system will reboot, apply the staged packages offline, and boot into the new release.
sudo dnf system-upgrade reboot
# Schedules the upgrade transaction to run at the next boot
# The init system switches to a special target that applies changes
# Your current desktop session closes immediately. Save your work.
The reboot process takes longer than a normal restart. The system is unpacking, verifying, and replacing thousands of files. Do not interrupt the power. When the machine finishes, log in and run a final refresh to catch any post-upgrade dependencies.
sudo dnf upgrade --refresh
# Applies any remaining patches that shipped after the base upgrade
# Ensures your system matches the latest stable state for the new release
sudo dnf autoremove
# Cleans up orphaned packages from the previous release
# Frees disk space and removes deprecated configuration files
Check the boot logs for warnings. Convention aside: journalctl -xe reads better than journalctl alone. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style.
journalctl -xe
# -x adds explanatory hints to standard log entries
# -e jumps to the end of the journal so you see recent events first
# Look for [FAILED] markers or dependency resolution warnings
Reboot before you debug. Half the time the symptom is gone.
Verify the new environment
Confirm the release version matches your expectation. The package manager tracks the release version in the fedora-release package. Query it to verify the transition completed.
rpm -q fedora-release
# Returns the exact version string of the installed release package
# Example output: fedora-release-41-1.fc41.noarch
Check that your critical services are running. Use systemctl status to view recent log lines and current state in one view. Always check status before restarting a unit.
systemctl status --state=failed
# Lists any units that failed to start during boot
# Empty output means all services reached their target state
Verify your network configuration. If you see [FAILED] Failed to start NetworkManager.service during boot, your network configuration probably references a missing interface name. Fedora switched to predictable network interface names years ago. Legacy eth0 references break on hardware changes or kernel updates.
nmcli device status
# Shows every network interface and its current connection state
# Verify that your primary interface shows "connected" and not "disconnected"
Run journalctl first. Read the actual error before guessing.
Common pitfalls and error patterns
Disk space exhaustion is the most common failure mode. The staging directory fills up, dnf aborts the transaction, and the system reboots into the old release. You will see a transaction rollback message in the journal. Clear the cache and free space before retrying.
sudo dnf system-upgrade clean
# Removes the downloaded package cache from /var/lib/dnf/system-upgrade/
# Frees disk space so you can retry the download phase
Stale third-party repositories cause dependency conflicts. If you forgot to disable a Copr repo, dnf will try to install packages built for the old kernel. The transaction test will fail with version mismatch errors. Disable the repo, clear the cache, and restart the download.
SELinux denials often appear after major upgrades. New package versions sometimes change file contexts or service capabilities. Convention aside: SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. Most denials resolve after a relabel or a service restart.
sudo restorecon -Rv /etc
# -R processes directories recursively
# -v prints every file that gets relabeled
# Fixes context mismatches caused by package file moves
Convention aside: firewall-cmd --reload after every rule change. Otherwise the runtime config and the persistent config diverge. Upgrades sometimes reset firewall zones. Verify your rules after the transition.
Trust the package manager. Manual file edits drift, snapshots stay.
Choose your upgrade path
Use dnf system-upgrade when you want a seamless in-place transition between supported releases. Use a clean installation when your current system has years of accumulated configuration drift or broken dependencies. Use dnf upgrade --refresh when you only need security patches and package updates within the same release. Stay on the current release when you are running production workloads that require stability over new features.