You run sudo dnf upgrade and the terminal refuses to move
You open a terminal to update your system. You type sudo dnf upgrade and hit enter. The command prints Another app is currently holding the dnf lock; waiting for it to exit... and stops. You wait. Nothing happens. You open a second terminal to investigate. You run sudo dnf check. Same message. The package manager is locked, and you cannot install, remove, or update anything until the lock is released.
This error is common. It rarely indicates a broken system. It usually means a background process is doing its job, or a previous run crashed without cleaning up. The fix is straightforward once you identify which process holds the lock and whether that process is still alive.
What the lock file actually does
DNF uses a lock file to prevent two processes from modifying the RPM database simultaneously. The RPM database stores metadata about every installed package. It uses Berkeley DB files under /var/lib/rpm/. BDB requires exclusive locks for write operations. If two processes write to the database at the same time, the indexes can diverge from the actual package headers. You end up with a system where rpm thinks a package is installed but the files are missing, or dependencies resolve incorrectly.
The lock file lives at /var/run/dnf/libdnf.pid. It contains the process ID of the DNF instance that currently holds the lock. When DNF starts, it checks for this file. If the file exists, DNF reads the PID and checks if that process is running. If the process is running, DNF waits. If the process is gone but the file remains, DNF assumes the previous run crashed and waits indefinitely.
The lock file is cheap insurance. Database corruption costs hours of recovery. Respect the lock.
Background maintenance is the usual suspect
Fedora runs dnf makecache periodically in the background to keep mirror metadata fresh. This process is managed by systemd and triggers every 15 minutes by default. The cache update acquires the DNF lock while it downloads metadata. You often see the lock error right after a fresh boot or after the system has been idle. The background job is running, holding the lock, and your manual command is waiting for it to finish.
Check the timer status to see if background maintenance is active.
systemctl status dnf-makecache.timer # Check the state of the background metadata timer
# Active: active (waiting) means the timer is armed and will trigger periodically.
# Trigger: ... shows when the next run is scheduled.
# If the timer is active, the lock is likely held by a scheduled cache update.
systemctl list-timers --all | grep dnf # List all DNF-related timers and their schedules
# This shows when dnf-makecache and dnf-automatic are scheduled to run.
# Disable timers if background updates interfere with your workflow.
If the timer is active and the lock appeared seconds ago, wait. The cache update usually completes within a few seconds. Interrupting it forces DNF to retry, which just re-acquires the lock.
Check the timer before you blame the lock. Background jobs are the usual suspect.
Inspect the lock and identify the holder
If waiting does not resolve the issue, inspect the lock file directly. The file contains the PID of the process that DNF believes owns the lock. Use that PID to verify if the process is actually running.
Here's how to read the lock file and check the process status.
sudo cat /var/run/dnf/libdnf.pid # Display the PID stored in the lock file
# Note the number printed. This is the process ID DNF thinks owns the lock.
# If the file is empty or missing, the lock state is undefined.
ps -p $(cat /var/run/dnf/libdnf.pid) # Check if that PID exists in the process table
# If this returns nothing, the process is dead and the lock is stale.
# If this returns a line with 'dnf' or 'python3', the process is still running.
# The output includes the PID, TTY, TIME, and COMMAND columns.
DNF often prints helpful context when it waits. If you see output like the following, DNF detected a running instance and is waiting. The State line tells you if the process is Sleeping or Running. If it's Sleeping for a long time, the process is likely stuck.
Another app is currently holding the dnf lock; waiting for it to exit...
The other application is: dnf
Memory : 88.0 M RSS (412.4 MB VSZ)
Started: Fri Feb 14 10:23:45 2025 - 00:15 ago
State : Sleeping, pid: 12345
Kill the stuck process or remove the stale lock
If the process is running but unresponsive, terminate it. If the process is dead, remove the lock file. Never remove the lock file while a process is actively writing to the database. That action leaves the RPM database in an inconsistent state.
Here's how to terminate a stuck process and clean up the lock.
sudo kill $(cat /var/run/dnf/libdnf.pid) # Send SIGTERM to request graceful shutdown
# SIGTERM allows the process to clean up locks and database transactions.
# Wait a few seconds to see if the process exits on its own.
sudo kill -9 $(cat /var/run/dnf/libdnf.pid) # Send SIGKILL if the process ignores SIGTERM
# SIGKILL forces termination immediately without cleanup.
# Use this only when the process is truly stuck and unresponsive.
# -9 sends a signal that cannot be caught or ignored by the target process.
sudo rm -f /var/run/dnf/libdnf.pid # Remove the lock file after the process is gone
# DNF will recreate this file automatically the next time it runs.
# Only remove the file if ps confirms no process holds the PID.
The RPM database has its own lock at /var/lib/rpm/.rpm.lock. DNF usually handles this internally, but if you ran rpm directly in another terminal, that lock might be the culprit. The same rules apply. Check the PID, kill if stuck, remove if stale.
Verify the package manager is functional
After clearing the lock, verify the RPM database is consistent and DNF can operate normally. Run a database check and force a metadata refresh.
Confirm the package manager is functional and the database is consistent.
sudo dnf check # Verify RPM database integrity without making changes
# This command scans for broken dependencies and conflicts.
# A clean run prints 'No problems found' or lists specific issues.
# If errors appear, the database may be corrupted and needs rebuilding.
sudo dnf upgrade --refresh # Force metadata refresh and apply pending updates
# --refresh ignores cached metadata and fetches fresh data from mirrors.
# This is the standard command for weekly system maintenance on Fedora.
# It ensures your system has the latest package versions and security fixes.
If dnf check reports errors, the database might be corrupted. Rebuild the database and clear all caches.
sudo rpm --rebuilddb # Rebuild the RPM database index from the installed package headers
# This scans /var/lib/rpm/Packages and regenerates the BDB indexes.
# It takes time proportional to the number of installed packages.
# Run this only if dnf check reports database errors.
sudo dnf clean all # Clear all cached metadata and lock files
# This removes /var/cache/dnf/* and ensures fresh data on next run.
# It also removes any stale lock files in the cache directory.
Run dnf check before you trust the system. A clean database is the baseline for every operation.
Common pitfalls and error patterns
The most dangerous mistake is removing the lock file while DNF is actively writing to the database. This leaves the RPM database in an inconsistent state. You might see Error: rpmdb: BDB0113 Thread/process ... died, is locked and didn't cleanup later. Always check the process status before deleting the lock file.
Another common issue is running DNF in multiple terminals. If you open two terminals and run sudo dnf upgrade in both, the second one will wait. This is expected behavior. DNF serializes access to prevent conflicts. Close the second terminal or let it wait. Interrupting with Ctrl+C cancels the wait but does not release the lock held by the first terminal.
The yum command is an alias for dnf on Fedora. Running sudo yum update acquires the same lock as sudo dnf upgrade. You cannot run yum and dnf simultaneously. The lock mechanism treats them as the same application.
If the lock persists despite removing the file and killing processes, the RPM database might be locked at the BDB level. A reboot clears all locks and reinitializes the database.
Reboot before you debug. Half the time the symptom is gone.
When to use each recovery action
Wait when the lock message appears immediately after boot. Fedora runs dnf makecache in the background to keep mirrors fresh.
Kill the process when the PID exists but the process is unresponsive and holding the lock for more than five minutes.
Remove the lock file when the PID in the file does not match any running process. The previous run crashed and left a stale artifact.
Reboot when the RPM database throws BDB errors or the lock persists despite removing the file. A reboot forces a clean state and runs fsck if needed.
Use journalctl -xeu dnf-makecache.service when you suspect the background timer is failing. The logs show whether the cache update succeeded or encountered network errors.
Trust the package manager. Manual file edits drift, snapshots stay.