The repository does not have a Release file
A 404 on one file, and three different reasons for it
E: The repository 'http://packages.example.com/debian stable Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
Most apt failures let the update finish. This one stops it, and says almost nothing about why. The repository answered: it served a 404 for one particular file, and the three reasons it might have done that need three different fixes.
What apt asked for, and where
sudo apt-get update 2>/dev/null
Ign:1 http://deb.tips-mirror.example:8086 buster InRelease
Err:2 http://deb.tips-mirror.example:8086 buster Release
404 File not found [IP: 127.0.0.1 8086]
Reading package lists...
Two fetches for what is one file to apt. InRelease is the modern form, the index with its
signature wrapped around it, and apt tries that first. Ign there is not a failure: a repository
is allowed to publish only the older pair, a Release file with a detached Release.gpg beside
it, so apt falls back rather than giving up. Err:2 is that fallback also coming back with a 404
error, at which point there is nothing left to try.
The URL apt built is worth being able to reconstruct:
URIs: http://deb.tips-mirror.example:8086
Suites: buster
gives http://deb.tips-mirror.example:8086/dists/buster/Release. dists/ is fixed, and the suite
is a directory name underneath it. So the error means that directory is not there.
sudo apt-get update 2>&1 >/dev/null; echo "exit: $?"
E: The repository 'http://deb.tips-mirror.example:8086 buster Release' does not have a Release file.
exit: 100
E rather than W, and exit 100. Every other source on the machine is refreshed, and the command
still fails, which apt update failed covers along with the
prefixes and the streams they arrive on.
Ask the server what it does have
curl -s -o /dev/null -w '%{http_code}\n' http://deb.tips-mirror.example:8086/dists/buster/Release
curl -s -o /dev/null -w '%{http_code}\n' http://deb.tips-mirror.example:8086/dists/stable/Release
404
200
The answer places you in one of the three cases. A 404 for your suite and a 200 for another
one means the repository is healthy and your suite is not there:
either it never was, or it has been retired. Fetching dists/ in a browser will usually list what
is, since most repositories leave directory indexes on.
A typo is the cheap explanation and worth ruling out first. bookwork for bookworm, or a
codename where the vendor publishes by role, are both instances of this error.
Debian's release channels has which names are codenames and which are
roles, and why a source may say either.
A release that has been archived
Debian keeps a release on the mirror network while it is supported. When support ends the release
does not vanish, it moves: the files leave deb.debian.org and reappear on archive.debian.org,
which exists to serve exactly this. A machine still pointing at the mirror asks for a directory
that has been taken away. It happens to every unattended machine running a release that has aged
out.
Pointing the source at the archive gets part of the way there:
sudo tee /etc/apt/sources.list.d/tips.sources >/dev/null <<'EOF'
Types: deb
URIs: http://archive.tips-mirror.example:8087
Suites: buster
Components: main
Signed-By: /etc/apt/keyrings/tips-repos.asc
EOF
sudo apt-get update 2>&1 >/dev/null; echo "exit: $?"
E: Release file for http://archive.tips-mirror.example:8087/dists/buster/InRelease is expired (invalid since 584d 14h 29min 16s). Updates for this repository will not be applied.
exit: 100
A different error: apt found the Release file this time and refused it. Every Release
file carries a Valid-Until date, and apt will not act on one that has passed. That check is there
so nobody can serve you a frozen copy of an old index to hide a security update from you, and on an
archived release it has passed by definition, because the release stopped being updated before the
date went by.
Then tell apt not to apply the check to that one repository:
sudo tee /etc/apt/sources.list.d/tips.sources >/dev/null <<'EOF'
Types: deb
URIs: http://archive.tips-mirror.example:8087
Suites: buster
Components: main
Signed-By: /etc/apt/keyrings/tips-repos.asc
Check-Valid-Until: no
EOF
sudo apt-get update >/dev/null 2>&1; echo "update exit: $?"
apt-cache policy tips-tool | head -3
update exit: 0
tips-tool:
Installed: (none)
Candidate: 1.0-1
Check-Valid-Until: no belongs in the stanza for the archived repository only. The
global form, Acquire::Check-Valid-Until "false"; in an apt.conf fragment, turns the check off
for every repository including the ones still getting security updates.
A repository with no dists directory at all
Some vendors publish a flat repository: the packages and one Packages index sitting together
in a single directory, with no dists/, no suites and no components. It is a legitimate layout,
but a stanza written in the ordinary shape asks it for a path that doesn't exist:
sudo tee /etc/apt/sources.list.d/tips.sources >/dev/null <<'EOF'
Types: deb
URIs: http://files.tips-vendor.example:8088
Suites: stable
Components: main
Signed-By: /etc/apt/keyrings/tips-repos.asc
EOF
sudo apt-get update 2>&1 >/dev/null; echo "exit: $?"
E: The repository 'http://files.tips-vendor.example:8088 stable Release' does not have a Release file.
exit: 100
Identical to the archived case, from a repository that is working perfectly. The two curl requests separate them:
curl -s -o /dev/null -w 'dists/stable/Release: %{http_code}\n' http://files.tips-vendor.example:8088/dists/stable/Release
curl -s -o /dev/null -w 'Packages at the root: %{http_code}\n' http://files.tips-vendor.example:8088/Packages
dists/stable/Release: 404
Packages at the root: 200
An index at the root with nothing under dists/ is a flat repository. The stanza for one names the
directory as the suite, with a trailing slash and no components at all:
sudo tee /etc/apt/sources.list.d/tips.sources >/dev/null <<'EOF'
Types: deb
URIs: http://files.tips-vendor.example:8088
Suites: ./
Signed-By: /etc/apt/keyrings/tips-repos.asc
EOF
sudo apt-get update >/dev/null 2>&1; echo "update exit: $?"
apt-cache policy tips-tool
update exit: 0
tips-tool:
Installed: (none)
Candidate: 1.0-1
Version table:
1.0-1 500
500 http://files.tips-vendor.example:8088 ./ Packages
The ./ in the last line is where a suite and component would normally be printed. If the packages
sit in a subdirectory rather than at the root, that subdirectory goes in Suites: with the same
trailing slash, and URIs: keeps the part above it.
When the suite is found and something else is not
A message beginning Skipping acquire of configured file and ending doesn't have the component
is the neighbouring mistake: apt read the Release file, so the suite is there, and the component
named beside it is not. main, contrib and non-free-firmware are Debian's; a vendor
repository often has exactly one and calls it something else. That one is a warning rather than an
error, so the update exits 0 and the packages are quietly missing.
For a source you are writing from scratch rather than repairing,
adding a third-party repository safely has the stanza with
every field explained, and apt covers the update workflow the source feeds.