What the error actually means
Every Docker client speaks to the Docker daemon through the Docker Engine API, and each API release is numbered: 1.24, 1.25, 1.40, 1.44, and so on. When a client connects, the daemon checks the API version the client negotiated. If the client version is below the minimum version the daemon supports, the daemon refuses the connection outright with an error like this:
Error response from daemon: client version 1.25 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version
(The exact wording varies by daemon version, but the phrase "client version 1.25 is too old" is the consistent giveaway.)
Watchtower is itself a Docker client: it talks to the daemon over /var/run/docker.sock to list containers, pull images, and recreate containers when new images appear. The original containrrr/watchtower image was last released as v1.7.1 back in November 2023, and it bundles a Docker API client from that era. When the daemon rejects that client, Watchtower cannot list a single container — so it cannot update anything. This is why the error repeats on every poll cycle.
To confirm this is your problem, check the Watchtower container's own logs:
docker logs watchtower --tail 50
If you see "client version 1.25 is too old" (or a similar "too old" API version message) repeated in the output, you have this exact problem.
Why Docker Engine 29 triggers it
The original Watchtower project was archived on December 17, 2025. No new releases were cut after v1.7.1, and the bundled Docker client library stopped tracking the Docker Engine API years earlier. Docker Engine, however, kept moving: each new engine release raises the API version it speaks, and eventually the daemon drops support for negotiating with clients that old.
Docker Engine 29 is the release where the door closed for the old client's negotiated version. The daemon now refuses API client version 1.25, and containrrr/watchtower cannot negotiate anything newer because the code is frozen in an archived repository. In other words, this is not a bug you introduced and not something your Docker host configuration caused — it is the predictable result of running an unmaintained client against a modern daemon.
This is also why the error appeared suddenly for so many people: nothing changed in their Watchtower setup. They ran a routine apt upgrade or a Docker Desktop update, the engine moved to Docker 29, and Watchtower broke the same hour. If you are still on Docker 27 or 28, you may not see the error yet — but the archived image will break for you the moment you upgrade the engine, so the fix below applies proactively too.
Why no config tweak can fix this. The failing code is the Docker client library compiled into the image. No environment variable, label, or command-line flag can make an archived binary speak a newer API version. Any guide telling you to adjust WATCHTOWER_* settings to fix this error is wasting your time. The image itself must be replaced.
The fix: switch to the maintained fork
The maintained fork of Watchtower is published on Docker Hub as nickfedor/watchtower, with source code at github.com/nicholas-fedor/watchtower. Its v1.20.x releases (current as of 2026) bundle a modern Docker API client that negotiates cleanly with Docker Engine 29. Every WATCHTOWER_* environment variable and every com.centurylinklabs.watchtower.* container label works identically to the old image, so migration is a straight image swap — your schedule, cleanup, and notification settings carry over untouched.
For background on the fork and the archived original, see migrating to the nickfedor fork and what the containrrr archival means.
Step 1 — Stop and remove the old container
Identify your current Watchtower container (it is usually named watchtower) and stop and remove it. This is safe: Watchtower keeps no state of its own, so deleting the container loses nothing.
docker stop watchtower
docker rm watchtower
Step 2 — Pull the maintained image
docker pull nickfedor/watchtower
Step 3 — Recreate Watchtower with your existing flags
Recreate the container exactly as you had it, only changing the image name. Here is the standard command for reference — keep whatever flags you were using before:
docker run -d \
--name watchtower \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-e WATCHTOWER_CLEANUP=true \
-e WATCHTOWER_SCHEDULE="0 0 4 * * *" \
nickfedor/watchtower
Note the WATCHTOWER_SCHEDULE format: Watchtower uses a 6-field cron expression where the first field is seconds, so "0 0 4 * * *" means 04:00:00 daily. If you previously used WATCHTOWER_POLL_INTERVAL (in seconds), you can keep using it unchanged — just not at the same time as a schedule. For a full reference of these variables, see Watchtower environment variables.
Docker Compose variant
If you run Watchtower through Compose, the fix is a one-line change in your docker-compose.yml:
services:
watchtower:
image: nickfedor/watchtower # was: containrrr/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 0 4 * * *
- TZ=UTC
Then pull the new image and recreate the service:
docker compose pull && docker compose up -d
The TZ variable is worth keeping if you use a schedule: it sets the timezone the cron schedule is evaluated in. See Watchtower Docker Compose setup for a complete working example.
Verifying the fix
After recreating the container, check its logs within a minute:
docker logs watchtower --tail 50
Healthy output looks like this — version banner, schedule confirmation, and successful image checks with no API errors:
time="..." level=info msg="Watchtower v1.20.x"
time="..." level=info msg="Using no notifications"
time="..." level=info msg="Checking all containers (except explicitly disabled with label)"
time="..." level=info msg="Scheduling first run: ..."
To force an immediate update check instead of waiting for the schedule, run a one-off check with the new image directly:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nickfedor/watchtower --run-once --debug
The --debug flag makes Watchtower log each image check, so you can confirm it is successfully talking to the daemon and evaluating your containers. If this run completes without the "too old" error, the fix is confirmed.
If updates still are not happening after the error is gone, work through the broader checklist in Watchtower not updating on Docker 29 or the general containers not updating guide — the API error is usually the first of several Docker 29 gotchas.
Preventing a repeat. Once you are on nickfedor/watchtower, enable notifications with WATCHTOWER_NOTIFICATION_URL so the next breaking change announces itself instead of failing silently — see Watchtower notifications. And keep an eye on whether Watchtower is still maintained and the troubleshooting index for new engine-version issues as they surface.