You ran rpm -i and now the system is broken
You downloaded a .rpm file from a vendor's website and ran sudo rpm -i package.rpm. The terminal spat back error: Failed dependencies: libfoo.so is needed by package. You tried installing libfoo manually, but that pulled in three more missing libraries. You are now stuck in a dependency loop. Or worse, you forced the install with --nodeps, and now your desktop environment won't start because a core library got overwritten.
The problem is not the package. The problem is the tool. You used a hammer to perform surgery.
What is actually happening
rpm and dnf both manipulate the same package database, but they operate at different levels of abstraction. rpm is the low-level engine. It writes files to disk, runs installation scripts, and updates the database. It does exactly what you tell it. It does not check if the package needs other packages. It does not talk to the internet. It does not care if you break the system.
dnf is the high-level manager. It talks to repositories, resolves the dependency tree, downloads everything needed, and then calls rpm to do the actual work. dnf protects you from yourself by ensuring every dependency is satisfied and every conflict is resolved before a single file is touched.
Think of rpm as a forklift. It moves boxes. If you tell it to drop a box on a pile of glass, it does. dnf is the warehouse manager. It checks the manifest, ensures the glass is packed, orders the missing parts, and then tells the forklift where to put things.
dnf is a frontend to rpm. When you run dnf install, it calculates the transaction and invokes rpm to execute it. This means dnf adds a layer of safety, dependency resolution, and transaction history on top of the raw file operations.
Run dnf install by default. Use rpm only for specific tasks where the high-level manager gets in the way.
The fix: use dnf for everything that involves installation
dnf install is the command for installing packages. It fetches packages from repositories and automatically resolves dependencies. It also handles local files correctly.
# Install a package from configured repositories
# dnf resolves all dependencies and downloads missing packages
sudo dnf install -y git
The most common mistake is assuming dnf cannot handle local files. It can. When you pass a local file path to dnf install, it treats the file as a package source and still resolves dependencies from your repositories. This is the correct way to install a downloaded RPM.
# Install a local RPM file while resolving dependencies from repositories
# dnf detects the local file path and treats it as a package source
# It still checks enabled repositories for missing dependencies
sudo dnf install ./vendor-tool-1.0-1.fc40.x86_64.rpm
This command is almost always what you want. It integrates the local package into the system safely. It records the transaction in dnf history, so you can undo it later. It prevents dependency hell.
Run dnf install ./file.rpm. Never guess dependencies manually.
Querying and verifying with rpm
Even when you install via dnf, the rpm tool remains the best way to query the system. dnf can query, but rpm is faster and has more granular flags for inspection. Use rpm when you need to find out what owns a file, list files in a package, or verify integrity.
# Query which package owns a specific file on disk
# rpm -qf searches the RPM database for the file path
# This is faster than dnf provides for local file lookups
rpm -qf /usr/bin/firefox
# List all files installed by a package
# rpm -ql shows the full path of every file managed by the package
# Use this to find config files or libraries without grepping
rpm -ql git
# Verify package integrity against checksums stored in the RPM database
# rpm -V compares file sizes, permissions, and hashes
# Output starts with S.M5DLUGT if any attribute differs
rpm -V git
The rpm -V command is powerful. It checks every file in the package against the metadata stored in the RPM database. If a file has been modified, the output shows which attribute changed. S means size, M means mode, 5 means MD5 hash. If the output is empty, the package is intact.
Check rpm -V to catch silent corruption. Trust the checksums.
Common pitfalls and error messages
rpm -i fails on existing packages
rpm -i installs a package. If the package is already installed, rpm -i fails with file ... conflicts with installed package. You need rpm -U to upgrade or reinstall. dnf install handles both cases automatically. It detects whether the package is new or an upgrade and acts accordingly.
# Upgrade or install a package using rpm
# rpm -U replaces an older version or installs if missing
# rpm -i only installs and fails if the package exists
sudo rpm -Uvh vendor-tool-1.0-1.fc40.x86_64.rpm
rpm --nodeps breaks the system
rpm --nodeps skips dependency checks. This is the nuclear option. It allows you to install a package even if dependencies are missing or conflicts exist. This leaves the system in an inconsistent state. Libraries may be missing, scripts may fail, and services may crash.
Use rpm --nodeps only when you are recovering a broken system and understand the risks. Never use it for routine installs.
# Force install ignoring dependencies (dangerous)
# Only use this when recovering from a broken state
# This bypasses all safety checks and can corrupt the system
sudo rpm -i --nodeps vendor-tool-1.0-1.fc40.x86_64.rpm
Conflicts with file from package
If you see file /path/to/file from install of package conflicts with file from package other, dnf will usually resolve this by swapping packages. rpm will just stop. dnf understands package relationships and can replace one package with another safely. rpm sees a file conflict and aborts.
If dnf refuses to resolve a conflict, check if you are mixing repositories from different Fedora releases. dnf cannot resolve dependencies across major version boundaries.
Run dnf upgrade --refresh before installing a local RPM to ensure your dependency database is current.
Transaction history and rollback
dnf records every transaction in a history database. You can undo changes, reinstall packages, or remove packages that were added in a specific transaction. rpm has no history. Once rpm writes files, there is no record of why they were installed.
# List recent DNF transactions
# The ID column is used for undo and redo operations
# Timestamps help identify when a change occurred
dnf history list
# Undo the most recent DNF transaction
# This restores files and removes packages added in the last operation
# Use dnf history list to find the transaction ID if needed
sudo dnf history undo last
This is a safety net. If an install breaks something, you can revert to the previous state. rpm offers no such protection.
Check dnf history before you panic. You can undo the last transaction.
When to use which
Use dnf install when you want dependency resolution and transaction history. Use dnf install ./file.rpm when you have a local file but still need dependencies from repositories. Use rpm -i when you are on an air-gapped system with no network and have pre-verified all dependencies. Use rpm -q when you need to query file ownership or package metadata quickly. Use rpm --nodeps only when you are recovering a broken system and understand the risks.
Edit files in /etc/. Files in /usr/lib/ are managed by rpm and will be overwritten on package updates.