Ubuntu APT Troubleshooting: Fix Broken Packages, Holds, and GPG Errors

Fix Ubuntu APT without guesswork.

Page content

APT failures are common on long-lived Ubuntu machines, and they usually appear after a release upgrade, a third-party repository change, a removed PPA, a manually installed .deb, or an interrupted package installation.

The error message can look dramatic, but most APT problems are not mysterious — they are state problems where APT’s view of repositories, versions, and installed packages no longer agrees.

laptop ubuntu apt packages

APT is trying to answer four questions:

  1. Which repositories are enabled?
  2. Which package versions are available?
  3. Which packages are already installed?
  4. Which package changes are allowed?

When those answers conflict, you get held packages, broken dependencies, missing public keys, bad PPA errors, or packages kept back during upgrade. This guide gives you a practical troubleshooting sequence for Ubuntu APT, written for developers, DevOps engineers, and Linux users who want to fix the system without blindly pasting random commands from forum threads. Pair it with our Ubuntu APT and dpkg cheatsheet for everyday install and upgrade commands, and browse the wider Developer Tools collection for related Linux workflows.

The Short Version

If your system is only mildly broken, start here:

sudo apt update
sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt update
sudo apt upgrade

If packages are kept back:

apt list --upgradable
apt-mark showhold
sudo apt full-upgrade

If a PPA or third-party repository is failing:

ls /etc/apt/sources.list.d/
sudo apt update

Read the failing repository line, then disable or fix that repository. If you see NO_PUBKEY, do not blindly import random keys from a keyserver — find the official repository instructions, install the repository key into /etc/apt/keyrings, and bind it to that repository with signed-by.

Before You Fix Anything: Read the APT Error First

Run this first:

sudo apt update

Do not skip it. apt update refreshes package metadata. It does not upgrade packages. It tells you whether Ubuntu can read all configured repositories and verify their metadata.

Then check your Ubuntu version and codename — a stale release name in /etc/apt/sources.list.d/ is a frequent cause of 404 and Release file errors. If you are unsure which release you are on, see how to check your Ubuntu version:

lsb_release -a

Or:

cat /etc/os-release

Also check what is upgradeable:

apt list --upgradable

And check whether any package is held:

apt-mark showhold

This gives you the first split in the decision tree — identifying the class of failure first makes troubleshooting easier because each class has a different first fix:

  • Repository problem: apt update fails.
  • Dependency problem: apt update works, but install or upgrade fails.
  • Held package problem: APT refuses to change specific packages.
  • Mixed source problem: A PPA, manual .deb, or old repository provides incompatible versions.
  • Interrupted install problem: dpkg has unpacked packages that were never configured.

Common Ubuntu APT Failure Types

Packages Kept Back

A kept-back package is not always an error; it means APT chose not to upgrade a package using the current command. This often happens when the upgrade requires installing new dependencies, removing old packages, or changing a package in a way that plain apt upgrade will not perform.

Check details:

apt list --upgradable
apt-cache policy package-name

Try a full upgrade only after reading what APT wants to do:

sudo apt full-upgrade

full-upgrade is allowed to install new packages and remove packages if needed to complete the upgrade. That is useful, but it is also why you should read the proposed changes before accepting. On a workstation, full-upgrade is usually fine after review; on a server, read the removals twice.

Held Packages

A held package is different from a package that is merely kept back. A hold is an explicit instruction that prevents APT from automatically installing, upgrading, or removing that package. Holds are useful for pinning a kernel, database, driver, or runtime version, and they are also easy to forget.

List held packages:

apt-mark showhold

Hold a package:

sudo apt-mark hold package-name

Remove a hold:

sudo apt-mark unhold package-name

If you see dependency errors involving a held package, decide whether the hold is still intentional. Do not remove holds automatically. They may be protecting a production service, driver, or compatibility-sensitive toolchain.

Broken Dependencies

Broken dependencies mean APT cannot find a valid package set, which usually points to a version conflict rather than a corrupted download.

Common causes include:

  • A package requires a version that is not available.
  • A PPA provides a newer library than Ubuntu expects.
  • A manually installed .deb depends on packages from another release.
  • A package install was interrupted.
  • A repository for the wrong Ubuntu release is enabled.
  • Package pinning or holds prevent the needed version change.

Start with:

sudo dpkg --configure -a
sudo apt --fix-broken install

Then inspect the package:

apt-cache policy package-name
apt-cache depends package-name
apt-cache rdepends package-name

Then use those commands to find the package version conflict that is blocking APT, rather than running every repair command in sequence.

GPG Key and NO_PUBKEY Errors

A NO_PUBKEY error means APT received repository metadata, but it cannot verify the signature because the required public key is missing — a trust problem, not merely a download problem.

A typical error looks like this:

The following signatures could not be verified because the public key is not available: NO_PUBKEY ABCD1234EF567890

Old instructions often used apt-key add, but avoid that for new repository setup. Modern Ubuntu systems should use a repository-specific keyring and signed-by.

A better pattern looks like this:

sudo install -d -m 0755 /etc/apt/keyrings

curl -fsSL https://example.com/repo-key.gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg

echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/example.list

sudo apt update

Replace the URL and repository line with the official instructions from the vendor.

The important part is this:

signed-by=/etc/apt/keyrings/example.gpg

That signed-by line binds the key to one repository, which is cleaner and safer than putting every third-party key into a global trust store.

Bad PPA or Release File Errors

PPA failures often look like this:

The repository does not have a Release file.

Or:

404 Not Found

Common causes:

  • The PPA does not support your Ubuntu release.
  • You upgraded Ubuntu, but the PPA still points to the old codename.
  • The PPA was deleted.
  • The maintainer stopped publishing packages.
  • You added a PPA intended for a different Ubuntu version.

Check your codename:

. /etc/os-release
echo "$VERSION_CODENAME"

List third-party source files:

ls /etc/apt/sources.list.d/

Inspect them:

grep -R "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/

Disable a suspect source by renaming it:

sudo mv /etc/apt/sources.list.d/example.list /etc/apt/sources.list.d/example.list.disabled
sudo apt update

If APT works after disabling the file, you have found the problematic source and can fix or remove it permanently.

A Safe APT Troubleshooting Workflow

Step 1: Refresh Metadata

sudo apt update

If this fails, fix repositories before trying package repair. APT cannot solve dependencies correctly if its package index is stale or incomplete.

Look for lines containing:

NO_PUBKEY
Release file
404 Not Found
does not have a Release file
The repository is not signed

These are repository or trust problems, and they should be fixed before you attempt any package repair.

Step 2: Finish Interrupted Package Configuration

If a package install was interrupted, dpkg may have unpacked files but not configured the package.

Run:

sudo dpkg --configure -a

If this succeeds, continue:

sudo apt --fix-broken install

If it fails, read the package name and error carefully. The package named at the bottom of the error is often more important than the package you originally tried to install.

Step 3: Ask APT to Repair Dependencies

sudo apt --fix-broken install

This command asks APT to correct dependency problems by installing missing dependencies or removing packages that cannot be satisfied. Read the proposed action carefully, especially any removals.

Be cautious if APT wants to remove:

  • ubuntu-desktop
  • ubuntu-server
  • linux-generic
  • display manager packages
  • network packages
  • database packages
  • container runtime packages
  • desktop environment packages

Sometimes removing a metapackage is harmless. Sometimes it is a warning sign that your package sources are mixed badly. Do not accept large removals without understanding them.

Step 4: Check Held Packages

apt-mark showhold

If a held package is blocking the upgrade, inspect it:

apt-cache policy package-name

If the hold is no longer needed:

sudo apt-mark unhold package-name
sudo apt update
sudo apt upgrade

If the hold is intentional, do not fight APT — fix the repository or package selection around the hold instead of removing the protection.

Step 5: Inspect Package Versions

For a package with dependency trouble:

apt-cache policy package-name

This shows:

  • Installed version
  • Candidate version
  • Available versions
  • Which repository provides each version

apt-cache policy is one of the most useful APT debugging commands because it shows where each available version comes from.

Example:

apt-cache policy docker-ce

If the candidate version comes from an unexpected PPA or old repository, you have found the likely cause of the dependency conflict.

Step 6: Look for Mixed Repositories

List enabled sources:

grep -R "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/

Look for:

  • Old Ubuntu codenames
  • Debian repositories on Ubuntu
  • PPAs for another Ubuntu release
  • Duplicate vendor repositories
  • Both Snap and APT instructions mixed for the same tool
  • Old .list files left behind after uninstalling software

A common anti-pattern is installing a tool from a vendor repository, then later adding a PPA or manual .deb that provides overlapping libraries. APT can handle many sources, but it cannot reconcile conflicting intentions unless you align the repositories yourself.

Step 7: Try a Simulated Install or Upgrade

Before making changes, simulate:

apt -s install package-name

Or:

apt -s full-upgrade

The -s option simulates the operation. It is useful when you want to see what APT would do without changing the system.

Fixing Held Packages

List Held Packages

apt-mark showhold

If nothing is printed, no packages are held with apt-mark, and you can move on to dependency or repository checks.

Hold a Package Intentionally

sudo apt-mark hold package-name

Good reasons to hold a package:

  • A kernel version is known to work with your hardware.
  • A database upgrade needs planning.
  • A driver update breaks your GPU.
  • A runtime version must match production.
  • A vendor package is not compatible with the latest dependency.

Bad reasons to hold a package:

  • You copied a command from an old guide.
  • You forgot why it was held.
  • You are avoiding a dependency error without understanding it.

Remove a Hold

sudo apt-mark unhold package-name

Then update and upgrade:

sudo apt update
sudo apt upgrade

If the package still will not upgrade, it was not only a hold problem. Check policy:

apt-cache policy package-name

Fixing Broken Dependencies

The Standard Repair Sequence

Use this sequence when package installation or upgrade failed halfway:

sudo apt update
sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt upgrade

This order matters because each step prepares the ground for the next: apt update refreshes repository metadata, dpkg --configure -a finishes configuring unpacked packages, apt --fix-broken install lets APT reconcile missing or conflicting dependencies, and apt upgrade resumes normal package upgrades.

Remove a Badly Installed Local Package

If the problem started after installing a downloaded .deb, inspect it:

dpkg -l | grep package-name
apt-cache policy package-name

Remove it:

sudo apt remove package-name

If configuration files are also causing problems:

sudo apt purge package-name

Then repair:

sudo apt --fix-broken install

Reinstall a Damaged Package

If a package is installed but broken:

sudo apt install --reinstall package-name

This is useful when files are missing or corrupted, but the package sources are otherwise healthy and you want to refresh the installed files without changing versions.

Fixing PPA and Third-Party Repository Problems

Find PPAs and Third-Party Repositories

ls /etc/apt/sources.list.d/

Show active repository lines:

grep -R "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/

On newer Ubuntu systems, you may also see .sources files using the deb822 format:

ls /etc/apt/sources.list.d/*.sources

Display them:

cat /etc/apt/sources.list.d/*.sources

Disable a PPA Safely

Rename the source file:

sudo mv /etc/apt/sources.list.d/example.list /etc/apt/sources.list.d/example.list.disabled
sudo apt update

For deb822 files:

sudo mv /etc/apt/sources.list.d/example.sources /etc/apt/sources.list.d/example.sources.disabled
sudo apt update

Renaming the source file is reversible and safer than deleting repository configuration immediately, because you can rename it back if you disabled the wrong source.

Remove Packages from a PPA

Disabling a PPA stops future package downloads from it. It does not automatically downgrade packages already installed from that PPA.

If the PPA caused library conflicts, you may need to downgrade packages back to Ubuntu versions.

Install ppa-purge:

sudo apt install ppa-purge

Then purge the PPA:

sudo ppa-purge ppa:owner/name

Use ppa-purge carefully and read the proposed changes before accepting, because it may remove or downgrade several related packages.

After a Release Upgrade

After upgrading Ubuntu, old PPAs are a common source of errors.

Check for old codenames:

grep -R "jammy\|noble\|oracular\|plucky" /etc/apt/sources.list /etc/apt/sources.list.d/

Adjust the codenames for your real system. For example, if you are on Ubuntu 24.04, your codename is noble. If a third-party source still points to an older codename, verify whether that vendor supports your current Ubuntu release. If you are setting up a new machine rather than repairing an upgrade, our Ubuntu 24.04 install guide walks through adding vendor repositories with signed-by from the start.

Do not just edit the codename and hope for the best — some repositories do not publish packages for every Ubuntu version, so verify vendor support for your release first.

Fixing GPG and NO_PUBKEY Errors

What NO_PUBKEY Means

APT repositories publish signed metadata, and your machine needs the matching public key to verify that metadata. If the key is missing, APT refuses to trust the repository, which is the behavior you want — do not disable signature checks just to make the error disappear.

The Modern Keyring Pattern

Create the keyring directory:

sudo install -d -m 0755 /etc/apt/keyrings

Download and dearmor the vendor key:

curl -fsSL https://example.com/repository-key.gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg

Set readable permissions:

sudo chmod 0644 /etc/apt/keyrings/example.gpg

Add the repository with signed-by:

echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/linux/ubuntu noble stable" \
  | sudo tee /etc/apt/sources.list.d/example.list

Then update:

sudo apt update

Replace noble with your Ubuntu codename if needed:

. /etc/os-release
echo "$VERSION_CODENAME"

Why apt-key Is the Wrong Habit

Old guides often use:

curl -fsSL https://example.com/key.gpg | sudo apt-key add -

Avoid apt-key add for new setups. The old apt-key style adds keys to a broad trust area, which makes it harder to reason about which key is trusted for which repository, whereas the modern signed-by style scopes the key to a specific repository and is basic supply-chain hygiene.

Find Legacy Trusted Keys

You may still have old keys in:

/etc/apt/trusted.gpg
/etc/apt/trusted.gpg.d/

List files:

ls -l /etc/apt/trusted.gpg.d/

Do not delete keys randomly — first map each key to a repository, then migrate one repository at a time to /etc/apt/keyrings and signed-by.

Common GPG Mistakes

Do not use random keyservers as your first choice when fixing NO_PUBKEY errors.

Better order:

  1. Use the vendor’s official install documentation.
  2. Download the key from the vendor’s official HTTPS URL.
  3. Store it in /etc/apt/keyrings.
  4. Bind it with signed-by.
  5. Run sudo apt update.

Avoid these shortcuts:

sudo apt update --allow-unauthenticated
sudo apt install --allow-unauthenticated package-name

They may work temporarily, but they remove the signature verification that protects you from tampered repository metadata.

Fixing “The Repository Is Not Signed”

This error usually means one of these things:

  • The repository does not publish signed metadata.
  • The repository URL is wrong.
  • The repository no longer supports your Ubuntu version.
  • A proxy or mirror is returning the wrong content.
  • You are using HTTP where the vendor now expects HTTPS.
  • The source file has the wrong suite or component.

Find the failing source:

sudo apt update

APT will print the URL. Then search for it:

grep -R "example.com" /etc/apt/sources.list /etc/apt/sources.list.d/

Disable it temporarily:

sudo mv /etc/apt/sources.list.d/example.list /etc/apt/sources.list.d/example.list.disabled
sudo apt update

If APT works again after disabling the file, reinstall that repository from the vendor’s current official instructions rather than re-enabling the old configuration.

Fixing Duplicate Repository Warnings

APT may warn that a target is configured multiple times.

List matching entries:

grep -R "repo-url-or-domain" /etc/apt/sources.list /etc/apt/sources.list.d/

Duplicate repositories often appear after running vendor install scripts multiple times.

Keep one source file. Disable the others:

sudo mv /etc/apt/sources.list.d/duplicate.list /etc/apt/sources.list.d/duplicate.list.disabled
sudo apt update

Duplicate warnings are not always fatal, but they are a sign of sloppy configuration, so keep one source file and disable the duplicates.

Fixing Packages from the Wrong Ubuntu Release

One of the worst APT problems is mixing Ubuntu releases — for example, a machine on Ubuntu 24.04 should not casually pull packages from Ubuntu 22.04 or Debian testing. Sometimes it works for a while, but eventually the dependency graph becomes a puzzle that APT cannot solve cleanly.

Check your release:

. /etc/os-release
echo "$VERSION_CODENAME"

Search sources:

grep -R "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/

Look for foreign codenames in the enabled sources, then inspect the affected package:

apt-cache policy package-name

If the installed version came from an old or foreign repository, disable that repository and downgrade or reinstall the affected package from Ubuntu repositories.

A conservative repair path is:

sudo apt update
sudo apt install --reinstall package-name

For deeper conflicts, you may need to remove the package and reinstall it from the correct source rather than forcing an upgrade over a foreign version.

Cleaning APT Cache and Unused Packages

APT cache cleanup is not a dependency fix on its own, but it can help after many failed installs by reclaiming disk space and clearing stale package files.

Remove packages that were installed automatically and are no longer needed:

sudo apt autoremove

Clean downloaded package files:

sudo apt clean

Or remove only obsolete package files:

sudo apt autoclean

Use autoremove carefully on servers and desktops with manually installed driver stacks, and read the removal list before accepting.

Practical APT Troubleshooting Recipes

Recipe: Package Is Kept Back

sudo apt update
apt list --upgradable
apt-mark showhold
sudo apt full-upgrade

If APT proposes reasonable changes after simulation, accept them. If it proposes large removals, stop and inspect:

apt-cache policy package-name

Recipe: Held Package Blocks Upgrade

apt-mark showhold
apt-cache policy package-name
sudo apt-mark unhold package-name
sudo apt upgrade

Only unhold a package if the hold is no longer intentional, because removing a hold that protects production software can trigger a breaking upgrade.

Recipe: Interrupted Install

sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt upgrade

Recipe: NO_PUBKEY Error

  1. Identify the repository from sudo apt update.
  2. Find the vendor’s current official install instructions.
  3. Install the key into /etc/apt/keyrings.
  4. Use signed-by in the source file.
  5. Run sudo apt update.

Example structure:

sudo install -d -m 0755 /etc/apt/keyrings

curl -fsSL https://example.com/key.gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg

sudo chmod 0644 /etc/apt/keyrings/example.gpg

echo "deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/ubuntu noble main" \
  | sudo tee /etc/apt/sources.list.d/example.list

sudo apt update

Recipe: PPA Does Not Have a Release File

sudo apt update
ls /etc/apt/sources.list.d/
grep -R "ppa.launchpadcontent.net\|launchpad" /etc/apt/sources.list.d/

Disable the PPA:

sudo mv /etc/apt/sources.list.d/example.list /etc/apt/sources.list.d/example.list.disabled
sudo apt update

Then decide whether to remove, replace, or purge packages from that PPA.

Recipe: Manual .deb Broke Dependencies

dpkg -l | grep package-name
apt-cache policy package-name
sudo apt remove package-name
sudo apt --fix-broken install

If you still need the software, prefer the vendor’s current APT repository over repeated manual .deb installs, which tend to accumulate dependency conflicts over time.

Essential APT Troubleshooting Commands

Repository and Metadata

sudo apt update
grep -R "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/
ls /etc/apt/sources.list.d/

Package State

apt list --installed
apt list --upgradable
apt-mark showhold
dpkg -l | grep package-name

Package Policy and Dependencies

apt-cache policy package-name
apt-cache depends package-name
apt-cache rdepends package-name

Repair

sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt install --reinstall package-name
sudo apt full-upgrade

Cleanup

sudo apt autoremove
sudo apt autoclean
sudo apt clean

Simulation

apt -s install package-name
apt -s full-upgrade

What Not To Do

Do Not Randomly Delete /var/lib/dpkg

If you see advice to delete dpkg state files, be skeptical. The dpkg database is the record of installed packages, and deleting pieces of it can turn a repairable package issue into a full system recovery project.

Do Not Disable Signature Verification

Avoid:

--allow-unauthenticated

If a repository cannot be verified, fix the key or disable the repository rather than bypassing authentication.

Do Not Mix Ubuntu Releases Casually

Do not add repositories for another Ubuntu release unless you understand APT pinning and the dependency consequences.

This applies especially to:

  • desktop environments
  • graphics drivers
  • Python stacks
  • container runtimes
  • Kubernetes packages
  • database packages

Do Not Treat PPAs as Harmless

PPAs are useful, but they are still package repositories that can replace libraries and system packages — which may be exactly what you want, or exactly why your next upgrade breaks. Prefer PPAs for specific applications, not for broad system foundations, unless you trust the maintainer and understand the upgrade path.

APT Troubleshooting Decision Tree

Use this mental model:

flowchart TD A["Does sudo apt update fail?"] -->|yes| B["Fix repositories, GPG keys, PPAs, network, or release files"] A -->|no| C["Did an install or upgrade get interrupted?"] C -->|yes| D["Run dpkg --configure -a, then apt --fix-broken install"] C -->|no| E["Are packages held?"] E -->|yes| F["Inspect apt-mark showhold and decide whether to unhold"] E -->|no| G["Are packages kept back?"] G -->|yes| H["Inspect apt full-upgrade simulation and package policy"] G -->|no| I["Is a third-party source involved?"] I -->|yes| J["Inspect apt-cache policy and source files"] I -->|no| K["Inspect the specific package dependency error"]

Most APT problems become manageable once you stop treating them as one big error and start separating repository health, package state, dependency solving, and trust configuration — the decision tree above is a shorthand for that discipline.

For a clean Ubuntu developer workstation, I prefer this baseline:

  • Keep Ubuntu repositories standard.
  • Use vendor APT repositories only when they are official and maintained.
  • Use /etc/apt/keyrings and signed-by for third-party repositories.
  • Avoid old apt-key instructions.
  • Avoid mixing PPAs that replace core system libraries.
  • Use containers, uv, pipx, asdf, mise, or language-native tools for fast-moving developer dependencies.
  • Keep APT responsible for the operating system, drivers, services, and stable CLI tools.

For desktop software, prefer Flatpak or Snap over PPAs when a sandboxed universal package fits your needs. APT is excellent when it manages the base system, but it becomes painful when it is forced to behave like a universal developer dependency manager for fast-moving language ecosystems.

Final APT Troubleshooting Checklist

When APT is broken on Ubuntu, work through this checklist:

[ ] Run sudo apt update and read the first real error.
[ ] Check Ubuntu codename with /etc/os-release.
[ ] Finish interrupted installs with dpkg --configure -a.
[ ] Repair dependencies with apt --fix-broken install.
[ ] Check held packages with apt-mark showhold.
[ ] Inspect package versions with apt-cache policy.
[ ] Disable broken PPAs or third-party repositories.
[ ] Replace apt-key style repositories with signed-by keyrings.
[ ] Simulate risky operations with apt -s.
[ ] Read removals before accepting full-upgrade or autoremove.

APT is not fragile, but it is strict, and that strictness is a feature: it prevents unsigned repositories, impossible dependency sets, and accidental package replacements from silently changing your system. The calm way to fix APT is to preserve that strictness, find the conflicting state, and repair the smallest thing that is actually wrong.

Subscribe

Get new posts on AI systems, Infrastructure, and AI engineering.