r/devops • u/CSE_GEEKboy • 2d ago
Troubleshooting GitHub Actions self-hosted runner gets stuck downloading Java 17 with setup-java — curl: (18) Transferred a partial file
I'm learning GitHub Actions and have set up a self-hosted runner inside an Ubuntu Docker container on my Windows machine.
My workflow uses actions/setup-java to install Java 17:
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: maven
However, the job gets stuck at the Set up JDK 17 step. The logs stop at:
Resolved latest version as 17.0.20+101
JDK cache is not found for Temurin-Hotspot 17.0.20+101
Trying to download...
Downloading Java 17.0.20+101 (Temurin-Hotspot) ...
I tested the download URL manually from inside the container using curl. The download repeatedly stops before completion and returns:
curl: (18) Transferred a partial file
I also tried resuming the download with curl -C - and retry options, but it failed again. A basic connectivity test to https://github.com returns HTTP 200.
The runner itself appears to be connected and running jobs correctly. I haven't yet confirmed whether the issue is related to the network, the GitHub release download redirect, a proxy, or something else.
My questions:
- What could cause
curl: (18) Transferred a partial fileto occur repeatedly when downloading a large release asset? - How can I identify whether the problem is caused by my network, a redirect destination, a proxy, or the download server?
- Is there a recommended way to configure
actions/setup-javaon a Docker-based self-hosted runner to avoid this issue?
I'd appreciate any troubleshooting steps or suggestions. Thanks!
2
u/sagacious123 1d ago
Did you try curl --retry 5 --retry-delay 2 --retry-all-errors -C -. Sometimes it works on a retry.
2
u/Immediate_Wheel1953 2d ago
I hit almost this exact thing with a Docker runner last year and I wasted an afternoon blaming setup-java. The Temurin JDK asset is a big download, so a flaky path fails exactly like this while tiny requests like the github.com health check sail through. In my case the container's MTU didn't match the host (VPN on the host side), and large transfers kept dying partway. Try curl -v on that release URL inside the container and watch which host it dies on; if it's the redirected objects.githubusercontent.com URL and the same download works from the host, suspect MTU or a proxy env var leaking into the container.
1
u/Rambo2521 1d ago
We used to experience this issue intermittently, but way back I believe v2 or 3.
Ultimately, we made the jdk available for download at a local server and picked it up from there. setup-java has a parameter where you can point from where to download the file.
Comes with the pro that running that action became much quicker, but needs consideration for other jdk versions.
Edit: I know this doesnt answer what the root cause for you may be, for that we were not sure either. But above has worked well for us.
1
u/QuietSignalOps 1d ago
Glad the v6 switch unblocked you, but the underlying path problem is probably still there, and the next big download will hit the same wall.
Quick way to isolate it, roughly in this order:
env | grep -i proxyinside the container. Docker Desktop on Windows is happy to leak the host's VPN or system proxy env vars into the container, and a mid-transfer reset on a large file with small requests fine is the classic proxy idle-timeout signature.curl -von the actual release URL. It 302-redirects to objects.githubusercontent.com, and the bytes come from there, not github.com. If the same download succeeds from the Windows host itself but dies from the container, the problem is in Docker Desktop's network path. A VPN on the host changing the effective MTU is a common one; a container/host MTU mismatch makes exactly this failure mode.- Note where it dies. If it stops at roughly the same byte offset every run, suspect a middlebox buffer or proxy cap. If the offset varies, suspect a flaky link or MTU blackhole.
The more important fix, and the real answer to your question 3: look at that log line "JDK cache is not found for Temurin-Hotspot 17.0.20+101". With a container-based self-hosted runner, each job gets a fresh container, so setup-java re-downloads the ~190MB JDK for every single job. You're re-exposing the flaky path on every run, forever. Two ways to make it stop:
- Mount a persistent
_work/_toolcachevolume in the runner's container action config. The JDK (and your Maven cache) survives between jobs, so only the first job ever downloads it. - Or bake Temurin 17 into the runner base image and skip the download entirely. Slowest-to-ship, fastest jobs, zero network dependency.
Also pin the version. java-version: '17' resolves to the newest patch (yours resolved to 17.0.20+101), and every time Temurin ships a patch release every runner re-downloads. Pin to the exact build you test with and the cache stays warm.
The download_url parameter someone else mentioned works too, but the toolcache volume is less fiddly and it fixes the Maven dependency cache at the same time.
1
u/Wooden_Jelly_5295 1d ago
Does the same download finish on the host but fail inside Docker? That comparison would narrow things down quickly.
0
u/SeniorIdiot Senior DevOps Idiot 2d ago
Why are you using a self-hosted runner if just experimenting? Just curious...
A GitHub Pro/Team license costs $4 per month and you get 3000 minutes of actions.
-2
u/ansibleloop 2d ago
Custom runner images and not having to deal with GitHub service outages
The actions scheduler that's built in doesn't work - I've had to build my own scheduler to work around their shit
2
u/burlyginger 1d ago
We use self hosted runners and still very much have to deal with GH service outages.
2
u/Potato-9 1d ago
Yeh there no way around that without a peer GitHub mirror to trigger CI from. A self hosted runner proxy that knew if the cloud was working or not would be pretty cool for that.
-6
7
u/Flettys 2d ago
Use a newer version of setup-java
https://github.com/actions/setup-java/releases/tag/v6.0.1