Repository navigation
Description
Type of problem
CI infrastructure - flaky job failure, not a product bug
Describe the situation
Integration test jobs fail before any test runs, with:
ERROR: Failed to pull the following image(s) after 3 attempt(s): ...
Failed to pre-pull Docker images needed by the test batch
Since 2026-11-04 this has happened five times in eight days, killing up to 24 Integration jobs in one run. The latest nightly MasterCI on antalya-26.6 (run 42931630136) lost all 24 Integration jobs that started between 01:03 and 01:47 UTC.
This issue:
- Fails the job before any test runs, so the shard reports no test results at all
- Isn't caused by the PR or commit under test. The job labels it
INFRAitself - Passes on rerun, or for shards that start later
- Affects every branch that has the pre-pull step:
antalya-26.6,antalya-26.8,stable-26.8. The 26.3 branches don't have it
Root cause analysis
This analysis was done with AI assistance (Claude), from the CI job logs and the CI database.
Where the pull stops
None of the failing pulls logs an HTTP error: no 429, 401 or 5xx. The manifest resolves and the layers are listed, but no layer starts downloading. Every layer stays in Waiting for the whole 300 s:
latest: Pulling from library/redis
37fb86c2a767: Pulling fs layer
...
37fb86c2a767: Waiting
e7012240c0fb: Waiting
Pull of redis failed on attempt 1 (300s elapsed)
Why a slow download becomes a failure
The pre-pull step comes from upstream ClickHouse#100039. ci/jobs/scripts/prefetch-integration-test-images:
- Starts a
docker pullfor every image in the batch at once. A batch needs 9 to 37 images. - Gives each pull 300 s, and retries 3 times.
- Fails the job if any image misses all three attempts.
The dockerd inside the integration runner downloads 3 layers at a time across all pulls. That's the default, because ci/jobs/scripts/docker_in_docker.sh doesn't set max-concurrent-downloads. The other layers wait in a queue, and each image's 300 s includes that wait. When downloads slow down, the images at the back of the queue time out before they start.
What slows the downloads
Download throughput per job drops by more than 10 times. In the good nightly of 2026-11-07, the whole prefetch took 19 to 76 s per job. In the 2026-11-11 nightly, it ran past 15 minutes and failed.
Load on the shared runner pool contributes, but it doesn't decide the outcome:
| Hour (UTC) | Integration jobs started | With pre-pull step | Pre-pull failures |
|---|---|---|---|
| 2026-11-04 21h | 32 | 28 | 12 |
| 2026-11-05 18h | 67 | 27 | 0 |
| 2026-11-05 21h | 66 | 28 | 12 |
| 2026-11-06 14h | 63 | 28 | 0 |
| 2026-11-11 01h | 86 | 34 | 26 |
The cause of the slowdown is still open. The candidates are:
- The registry proxy. The integration dockerd pulls Docker Hub images through
dockerhub-proxy.dockerhub-proxy-zone:5000. Upstream traced the same symptom to its own proxy running out of connections (ClickHouse#108975). The proxy can't explain everything: images from ghcr.io and quay.io, which bypass it, also stall. - Hetzner outbound network, or a registry.
Upstream runs the same script and has had no pre-pull failures since 2026-10-09. The problem is in our download path, not in the script alone.
Occurrences
Jobs that failed at pre-pull on antalya-26.6, antalya-26.8, stable-26.8, their tags, and PRs against them. Source: gh-data.checks (test_name = '' and test_context_raw LIKE '%pre-pull%'), with the image list checked in job.log.
| Date (UTC) | Run | Failed jobs | Example job |
|---|---|---|---|
| 2026-09-09 22h | PR #2300 - 34388936376 | 4 | 102667572174 |
| 2026-09-29 23h | PR #2398 - 36619412769 | 1 | 109661053065 |
| 2026-10-08 16h | MasterCI v26.6.8.20001.altinityantalya - 37794619231 |
1 | 113412975749 |
| 2026-10-22 15h | MasterCI stable-26.8 - 39794620463 |
6 | 119898422731 |
| 2026-11-04 01h | MasterCI antalya-26.6 nightly - 41747109440 |
9 | 126313976363 |
| 2026-11-04 21h | MasterCI v26.6.8.20003.altinityantalya - 41911689821 |
10 | 126879804127 |
| 2026-11-04 21h | PR #2778 - 41890885261 | 2 | 126884001889 |
| 2026-11-05 21h | PR #2801 - 42083048156 | 12 | 127535703863 |
| 2026-11-06 13h | PR #2801 - 42204670414 | 1 | 127924912564 |
| 2026-11-11 01h | MasterCI antalya-26.6 nightly - 42931630136 |
24 | 130243651869 |
| 2026-11-11 01h | PR #2588 (antalya-26.8) - 42923118560 |
2 | 130240782076 |
The table leaves out 84 jobs from 2026-09-13 to 2026-09-21. Those failed only on minio/minio and minio/mc, after Docker Hub removed those images. The clickhouse/minio-minio mirror fixed that, and it's a separate cause.
Expected behavior
The pre-pull step finishes when downloads are slow. The job runs late but doesn't fail.
Actual behavior
When download throughput drops, images wait in the dockerd queue past their 300 s limit. The job fails after about 16 minutes.
Proposed fix
- Time out the whole stage, not each image. Give the prefetch one limit (for example 20 minutes) and retry only on real errors. Queue time then stops counting against single images.
- Find what slows the downloads. Check the
dockerhub-proxyand network logs for the windows in the table. During the next wave, inspect a stuck runner withssto see where the stalled connections go. - Stagger the nightly MasterCI schedules.
antalya-26.6,antalya-26.3andstable-26.3start in the same second today. This lowers the risk but doesn't fix the cause. - Port ClickHouse#120107. It stops the tests from pulling again the images the prefetch already pulled. It's missing from
antalya-26.6,antalya-26.8andstable-26.8.
ClickHouse#101970 added retry_infra_failures.yml to rerun these failures automatically. It's disabled in this repository, and it only covers PR runs, not MasterCI.
Activity
[-]CI: Integration jobs on antalya-26.6 fail at "pre-pull Docker images" when several runs share the runner pool[/-][+]CI: Integration jobs fail at "pre-pull Docker images" when image downloads slow down[/+]CarlosFelipeOR commentedon Nov 12, 2026
Update: this issue affects
stable-26.3andantalya-26.3as well, and it is worse there. It's causing thousands of failures.The 26.3 branches don't have the pre-pull step, but the same slowdown hits them. There, it shows up as thousands of test failures instead of one failed step per job.
What happens without pre-pull
Without the prefetch, each integration test module pulls its images inside the cluster fixture during setup. When the pull stalls, the fixture hits the pytest timeout (
Failed: Timeout (>900.0s) from pytest-timeout). pytest then reports every test in that module as failed, so one stalled pull becomes one failure per test in the module.Occurrences on the 26.3 branches
antalya-26.3, the commit tagged as v26.3.60.20002 - 42137193109antalya-26.3nightly - 42931631027stable-26.3nightly - 42931631671Both 11-11 runs started in the same second as the
antalya-26.6nightly (42931630136), which lost 24 jobs at pre-pull. That is the 2026-11-11 01h wave in the table above.Why this matters
INFRA.antalya-26.3release commit.Suggested additions to the proposed fix
antalya-26.3andstable-26.3to the affected branches.INFRAfailure per job, which is easy to recognize and rerun.Analysis done with AI assistance (Claude), from the CI reports, job logs and the CI database.