Fix duplicate apt sources and deb822 files
apt update says a target is configured multiple times. Find the legacy .list and deb822 .sources pair, keep one, and get a clean update run back.
What the duplicate apt sources error means
Duplicate apt sources mean one repository is declared twice, in two different files, and APT (advanced package tool) has found both copies. On Ubuntu 24.04 and newer this almost always happens because a third party install script wrote an old one line .list file while a deb822 .sources file for the same repository was already on disk. Nothing is corrupt and no package is at risk. Delete one of the two declarations and the message goes away.
This is the line people paste into a search box:
W: Target Packages (stable/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/docker.list:1 and /etc/apt/sources.list.d/docker.sources:1Read it from the end. Two files, each with a line number, declare the same thing. Target Packages is the index apt downloads to learn which packages a repository offers, and stable/binary-amd64/Packages names the component (stable) and the architecture (amd64) that index covers. So apt is telling you that the amd64 index for the stable component is configured in docker.list at line 1, and again in docker.sources at line 1.
On apt 3.0 and newer, which means Ubuntu 25.04 onward and Debian 13, the same message starts with Warning: instead of W:. The text after the prefix is the same.
That warning is the mild case. apt merges the two declarations and the update still runs, because both describe the same archive with the same key. The hard case stops everything:
E: Conflicting values set for option Signed-By regarding source https://download.docker.com/linux/ubuntu/ noble: /usr/share/keyrings/docker-archive-keyring.gpg != /etc/apt/keyrings/docker.asc
E: The list of sources could not be read.apt refuses here because the two declarations name different signing keys for one archive. It will merge two identical declarations, but it will not choose between two Signed-By values, because picking the wrong one means checking package signatures against a key the archive owner never signed with. So apt reads no sources at all. apt update and apt install both fail with those same two lines until you edit the files by hand.
How the duplicate gets there
The two formats live in separate files with different extensions, so nothing on disk stops both from existing. apt notices the overlap late, when it expands every source file into the list of index targets it plans to fetch. Until that moment docker.list and docker.sources are two unrelated files.
Four ordinary events produce the pair:
- A vendor install script, or a command copied from an older post, writes
/etc/apt/sources.list.d/vendor.listwith ateeline. - The vendor's own package later ships
/etc/apt/sources.list.d/vendor.sourcesand installs it for you. add-apt-repositoryon Ubuntu 24.04 and newer writes deb822.sourcesfiles, so a PPA (personal package archive) you once added by hand as a.listcomes back as a.sources.- A release upgrade rewrote the distribution's own sources into deb822 and left your hand written
.listfile untouched beside them.
Each path is reasonable on its own. The duplicate is what you get when two of them happen on the same box, often months apart.
The two formats, side by side
The old format is one line per repository, and every part of it is positional.
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stableThe order is fixed: the type (deb for binary packages, deb-src for source packages), then options in square brackets, then the URI (uniform resource identifier) of the archive, then the suite, then one or more components. Because the meaning comes from position, a space in the wrong place changes what apt reads.
deb822 states the same thing as a stanza of named fields. The name comes from RFC 822, the mail header style that Debian already uses for package control files.
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.ascSame repository, same key, nothing added. The mapping is direct: deb becomes Types, the archive address becomes URIs, the suite becomes Suites, the components become Components, and each bracket option becomes its own field, so signed-by= becomes Signed-By: and arch= becomes Architectures:.
Every field name is plural because every field takes a space separated list. Suites: noble noble-updates noble-backports in one stanza replaces three separate deb lines. A blank line ends a stanza, so a single .sources file can hold several repositories. deb822 also carries settings the one line format handles poorly: Enabled: no to switch a repository off, Trusted, Check-Valid-Until, and an inline key pasted straight into Signed-By with every line indented one space and blank lines written as a single dot.
Where each file lives
/etc/apt/sources.list: the original single file. On Ubuntu 24.04 and newer it is usually empty or holds only a comment pointing at the new location./etc/apt/sources.list.d/*.list: one line entries, normally one file per repository./etc/apt/sources.list.d/*.sources: deb822 stanzas. Ubuntu 24.04 and newer keep the distribution's own repositories here, inubuntu.sources./etc/apt/keyrings/: where keys you add belong./usr/share/keyrings/holds keys that came from a package.
apt reads only files ending in .list or .sources, and a filename may contain letters, digits, underscore, hyphen and period. A file with any other extension is skipped with a notice, which matters for the fix below.
Find the duplicate pair
Start with the directory listing:
ls -l /etc/apt/sources.list.d/-rw-r--r-- 1 root root 195 Aug 3 09:12 docker.list
-rw-r--r-- 1 root root 254 Aug 9 14:40 docker.sources
-rw-r--r-- 1 root root 2683 Jun 11 08:02 ubuntu.sourcesTwo files with the same stem and different extensions are the common pair, but do not trust the names. Read the contents, because a duplicate can hide in a file called anything:
grep -rn -E '^(deb |deb-src |Types:|URIs:|Suites:|Signed-By:)' /etc/apt/sources.list /etc/apt/sources.list.d//etc/apt/sources.list.d/docker.list:1:deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable
/etc/apt/sources.list.d/docker.sources:1:Types: deb
/etc/apt/sources.list.d/docker.sources:2:URIs: https://download.docker.com/linux/ubuntu
/etc/apt/sources.list.d/docker.sources:3:Suites: noble
/etc/apt/sources.list.d/docker.sources:6:Signed-By: /etc/apt/keyrings/docker.ascThe pair is the two entries with the same host and the same suite. Both point at https://download.docker.com/linux/ubuntu and the suite noble, so they are the same repository written twice. Their Signed-By paths also disagree, which is what produces the Conflicting values error shown earlier.
Use grep rather than an apt command for this step. When apt is already stopping on the conflict it cannot list your sources either, so apt-cache policy prints the same error instead of the answer you want.
Fix it: keep the deb822 file, remove the legacy one
Keep the .sources file. It is the format apt tooling writes now, and it is where both Debian and Ubuntu are heading. Before deleting anything, check which of the two key paths exists on disk:
ls -l /etc/apt/keyrings/ /usr/share/keyrings/ | grep -i docker-rw-r--r-- 1 root root 4813 Aug 9 14:40 docker.ascOnly /etc/apt/keyrings/docker.asc is present, so the deb822 file is the one telling the truth and the .list file points at a key that was removed. If it turns out the file you plan to keep names the missing key, copy the working path into it first, then delete the other file.
Move the legacy file out of the directory rather than deleting it outright:
sudo mkdir -p /root/apt-sources-backup
sudo mv /etc/apt/sources.list.d/docker.list /root/apt-sources-backup/
sudo apt updateRenaming it to docker.list.bak and leaving it in place also works, because apt ignores unknown extensions, but then every apt run prints this:
N: Ignoring file 'docker.list.bak' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extensionMoving the file somewhere else keeps that notice off your screen and still keeps the backup. A healthy apt update afterwards looks like this, with no line naming two files:
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 https://download.docker.com/linux/ubuntu noble InRelease [48.8 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 175 kB in 1s (146 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.Now confirm the repository survived the edit:
apt-cache policy | grep download.docker.com 500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
origin download.docker.comIf a vendor's documentation still assumes the one line file, you can keep that one and delete the .sources file instead. One rule decides it either way: exactly one file may declare a given archive and suite.
Why one broken third-party source wedges apt update
The neighbouring failure looks different and has the same root, a third party source apt cannot use. The first version is a missing key:
Err:5 https://download.docker.com/linux/ubuntu noble InRelease
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.The Signed-By field is missing, or it points at a file that is not a usable key, so apt cannot verify the signature on the archive's InRelease file. It then throws that whole repository away rather than trust package lists it cannot check. Look at the key file itself:
ls -l /etc/apt/keyrings/docker.asc
gpg --show-keys /etc/apt/keyrings/docker.ascA working key prints a pub line with a key id and a uid line naming the vendor. gpg: no valid OpenPGP data found. means the file is not a key at all, which usually means the download saved an error page because the key URL moved. Fetch the key again, check the file, then run apt update.
The second version arrives after a release upgrade:
Err:6 https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky InRelease
404 Not Found [IP: 10.0.0.80 443]
E: The repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky Release' does not have a Release file.The PPA has published nothing for that suite, so the path does not exist on the server and the request returns 404. Your other repositories still update, and the packages you already have are untouched. The run exits non-zero, though, so any script that checks the exit status of apt update now reports a failure every time it runs. That is why one dead source is worth clearing on a box with unattended security upgrades configured: the daily noise is where a real failure hides.
Disable one source without breaking the rest
For a deb822 file, add one field to the stanza and save it:
Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu
Suites: plucky
Components: main
Signed-By: /etc/apt/keyrings/ondrej-php.asc
Enabled: noThe apt manual recommends this over commenting out each line of the stanza, and it is easier to undo. For a one line file, put a # at the start of the line. For either format, moving the file out of /etc/apt/sources.list.d/ also works, and that is the option to pick when the repository is gone for good.
Run sudo apt update again. The Err: block for that repository disappears, and the exit status returns to 0, which you can check with echo $? on the next line.
Never fix a broken source with sudo rm /etc/apt/sources.list.d/*. On Ubuntu 24.04 and newer that deletes ubuntu.sources, which holds the distribution's own repositories, so apt is left with no package lists at all and reports E: Unable to locate package curl for software that obviously exists. If you have already run it, write the file back:
Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpgSave that as /etc/apt/sources.list.d/ubuntu.sources, with noble replaced by your own release name from lsb_release -cs, then run sudo apt update.
Convert legacy .list files to deb822
As of August 2026, apt 3.0 and newer ship a converter for this. Debian 13 has it, and so does Ubuntu 25.04 and every release after it, including 26.04. Check the version, then run it:
apt --version
sudo apt modernize-sourcesIt rewrites the one line files under /etc/apt/sources.list.d/ as deb822 .sources files. Read what it prints, then list the directory yourself and run apt update before you trust the result. Ubuntu 24.04 ships an older apt with no such subcommand, and there the command answers E: Invalid operation modernize-sources. On that release, convert by hand with the field mapping above.
Converting is optional today, because apt still reads both formats. It is worth doing on a server you plan to keep, since every tool that writes sources now writes deb822, and a box with only .sources files cannot grow this class of duplicate.
Keep third-party sources tidy on a server
Third party repositories are the part of a server that ages worst. Each one is a promise by somebody else to keep publishing for your Ubuntu release, and a release upgrade tests every one of those promises on the same afternoon.
- Add a third party repository only when the distribution package will not do the job. A plain LAMP stack on Ubuntu 24.04 needs none: the Ubuntu archive carries every package it uses, with security updates for the life of the release.
- Keep keys in
/etc/apt/keyrings/, one file per vendor, mode 644. The unprivileged_aptuser does the downloading and has to read the key, so a key file readable only by root gives a permission error on every fetch from that repository. - Point
Signed-Byat that exact file in every stanza. A key sitting in/etc/apt/trusted.gpgor/etc/apt/trusted.gpg.d/is trusted for every repository on the box, which means a vendor key added years ago can validate packages from anywhere. - Before a release upgrade, read your sources and check that each vendor already publishes for the suite you are moving to.
A key in the old global keyring announces itself on every update:
W: https://download.docker.com/linux/ubuntu/dists/noble/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.Export that single key into its own file, then point the stanza at it:
gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --export 7EA0A9C3F273FCD8 | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/docker.gpgAdd Signed-By: /etc/apt/keyrings/docker.gpg to the repository's stanza and run sudo apt update. The warning stops once no repository depends on the old keyring, and you can then drop the entry with sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --delete-key 7EA0A9C3F273FCD8.
One more habit saves the most pain. do-release-upgrade disables third party sources for the upgrade and leaves them switched off afterwards, and turning them back on by hand, one at a time, is precisely where duplicate declarations get created. Read the Ubuntu 24.04 to 26.04 upgrade guide before you start, and write down which repositories you still need. On a machine you have only just built, the cheapest moment to get sources right is during the first ten minutes on a new VPS, while the only entries on the box are the ones Ubuntu shipped.
FAQ
Why does apt say a target is configured multiple times?
Because two files under /etc/apt/sources.list.d/ declare the same repository, suite and component. The message names both files with line numbers, such as docker.list:1 and docker.sources:1. apt merges them and carries on, so the update itself still works. The duplicate is worth clearing anyway: as soon as the two files name different signing keys, apt stops with E: Conflicting values set for option Signed-By and refuses to read any source at all, which blocks apt install too.
Should I keep the .list file or the .sources file?
Keep the .sources file. deb822 is what add-apt-repository writes on Ubuntu 24.04 and newer, it holds one named field per setting instead of positional text in square brackets, and it is where the distributions are heading. Before deleting the .list file, confirm the Signed-By path inside the .sources file points at a key that exists, with ls -l /etc/apt/keyrings/. Move the old file out of /etc/apt/sources.list.d/ instead of renaming it inside the directory, because a leftover .bak name makes apt print an ignored-file notice on every run.
How do I turn off one apt repository without removing it?
In a deb822 .sources file, add Enabled: no to the stanza. In a one line .list file, put a # at the start of the line. Either way, run sudo apt update afterwards and the Err: block for that repository disappears. This is the right move when a third party repository has no packages for your Ubuntu release yet and its 404 is making apt update exit non-zero.
Is the one line sources.list format going away?
It is deprecated, not removed. apt still reads .list files and will for a long time, so nothing on your server breaks tomorrow. New tooling writes deb822: Ubuntu 24.04 and newer keep the distribution repositories in /etc/apt/sources.list.d/ubuntu.sources, and add-apt-repository writes .sources files. On apt 3.0 and newer, sudo apt modernize-sources converts the files you still have.