1. Are you on the archived containrrr image?
This is the cause in the overwhelming majority of Docker 29 cases. The original containrrr/watchtower image was archived on December 17, 2025, with its last release (v1.7.1) dating back to November 2023. Its bundled Docker client is too old to negotiate with the Docker 29 daemon, so Watchtower can neither list containers nor pull images.
Check which image your container is running:
docker inspect watchtower --format '{{.Config.Image}}'
If the answer is containrrr/watchtower (or anything other than the maintained fork), switch images. The fix, including the compose variant and log verification, is covered step by step in fixing the "Client Version 1.25 Is Too Old" error — the short version is:
docker stop watchtower && docker rm watchtower
docker pull nickfedor/watchtower
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
The fork at nickfedor/watchtower (source: github.com/nicholas-fedor/watchtower, current v1.20.x as of 2026) accepts every WATCHTOWER_* environment variable and com.centurylinklabs.watchtower.* label exactly as before, so nothing else needs to change. See the full migration guide if you want the background first.
2. Look for API mismatch errors in the logs
Even on the right image, the logs are the fastest way to diagnose "not updating." Always start here:
docker logs watchtower --tail 50
On the old image you will see the signature failure:
Error response from daemon: client version 1.25 is too old
On the fork, look for any of these update-blocking patterns instead:
- "No new images found" on every run — the image checks are succeeding but nothing is newer upstream. This is normal behavior, not a failure; see step 3 for why your specific containers might still be pinned.
- Authentication failures against a registry — usually a private registry login problem (step 5).
- "Skipping container ... no matching label" — the label opt-in gotcha (step 4).
If you want per-container detail, force a single check run with debug output:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nickfedor/watchtower --run-once --debug
The --debug flag logs every image check decision, which makes it obvious whether Watchtower is skipping a container, failing to reach a registry, or simply finding nothing new.
3. Check :latest vs pinned tag behavior
Watchtower updates containers by pulling the same tag the container was created from and comparing the image digest. This leads to two common surprises on Docker 29 setups:
| Situation | What happens |
|---|---|
Container was created from myapp:latest | Watchtower pulls :latest and updates when the digest changes. Normal behavior. |
Container was created from a pinned tag like myapp:2.4.1 | Watchtower only checks that exact tag. If you expected it to move to 2.5.0, it never will — pinned tags are stable by design. |
| Container was created from an image ID or digest | There is no tag to re-pull. Watchtower skips the container. |
| You edited the tag in Compose but did not recreate the container | Watchtower still sees the old tag baked into the running container. Run docker compose up -d so the container actually uses the new tag. |
A useful rule: if you want rolling updates, point the container at a floating tag like :latest (or a branch tag your CI moves); if you pin versions, accept that Watchtower will only refresh the pinned tag itself. Also check WATCHTOWER_CLEANUP=true — without it, old images pile up, and with limited disk space a pull can fail silently mid-update.
Digest subtlety: some registries re-push the same digest under :latest after a rebuild. Watchtower compares digests, not timestamps, so if the upstream rebuild produced an identical image, "no update available" is the correct answer.
4. The label_enable opt-in gotcha
If you run Watchtower with WATCHTOWER_LABEL_ENABLE=true, it switches to opt-in mode: only containers carrying the label com.centurylinklabs.watchtower.enable=true are updated, and everything else is silently skipped. After an upgrade, people often discover this flag was in an old compose file or systemd unit they forgot about.
Check how your Watchtower container was started:
docker inspect watchtower --format '{{json .Config.Env}}' | tr ',' '\n'
If you see WATCHTOWER_LABEL_ENABLE=true, you have two options: either add the enable label to every container you want updated:
labels:
- "com.centurylinklabs.watchtower.enable=true"
...or remove the variable so Watchtower manages everything except containers explicitly disabled with com.centurylinklabs.watchtower.enable=false. The full label reference is at Watchtower container labels. Also double-check you did not accidentally set the disable label (or WATCHTOWER_MONITOR_ONLY=true) on the containers you expected to be updated — monitor-only mode logs "would update" without ever touching the container.
5. Registry authentication
Watchtower authenticates to registries using the Docker config of the host (typically ~/.docker/config.json) mounted into the Watchtower container, or via credentials configured for the container itself. After a Docker 29 upgrade — especially a fresh install or a move to Docker Desktop — that config file may be missing, have wrong permissions, or contain an expired token.
Symptoms: --debug logs show unauthorized or authentication required when checking images on a private registry, while public Docker Hub images update fine. Fixes:
- Re-run
docker login your-registry.example.comon the host and restart Watchtower so it picks up the refreshed credentials. - If you run Watchtower in a way that does not see the host's
~/.docker/config.json, mount it explicitly with-v ~/.docker/config.json:/config.jsonand point Watchtower at it if needed. - Check token expiry: some registries (and Docker Hub personal access tokens) expire silently. A token that worked in 2025 may simply be dead in 2026.
For notification setup so you actually hear about failed checks, see Watchtower notifications (WATCHTOWER_NOTIFICATION_URL). And if updates still refuse to happen after all five checks, fall back to the version-agnostic general not-updating troubleshooting guide or the main troubleshooting index.
6. Confirm updates actually resume
Once you have worked through the five checks, do not just assume the nightly schedule will take care of the rest — force a check immediately and watch it succeed:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nickfedor/watchtower --run-once --debug
In the debug output you should see each container evaluated, images pulled without authentication or API errors, and digests compared. If a container updates, Watchtower recreates it with the same configuration it had — ports, volumes, and environment variables are preserved automatically. If you enabled WATCHTOWER_NOTIFICATION_URL, you will also get a notification confirming the update, which doubles as proof your notification channel works for the next time something goes wrong.
One last thing to clean up: after the switch, remove the stale containrrr/watchtower image so nothing accidentally recreates the old container from it:
docker rmi containrrr/watchtower
With the old image gone, the maintained fork in place, and a successful forced check in the logs, your Docker 29 host is back to self-updating — and protected against the next engine upgrade too.