curl --retry: Retry Transient Failures
Networks in CI are flaky, and --retry handles transient errors without custom loops.
Transient timeouts and 5xx responses are common on shared runners. curl has built-in retry logic so you do not need a hand-rolled loop.
What it does
--retry <n> retries a failed transfer up to n times. By default curl only retries on transient errors: timeouts and certain 5xx responses (500, 502, 503, 504, 408, 429), and it uses exponential backoff starting around one second. --retry-all-errors (curl 7.71+) extends retries to all errors, including connection failures. --retry-connrefused (curl 7.52+) adds retry when the connection is refused.
Common usage
curl --retry 5 https://api.example.com/x
curl --retry 5 --retry-delay 2 --retry-max-time 60 https://api.example.com/x
curl --retry 5 --retry-all-errors --retry-connrefused https://api.example.com/x
curl -fsS --retry 4 --retry-all-errors -o build.tar.gz https://artifacts/xFlags
| Flag | What it does |
|---|---|
| --retry <n> | Retry up to n times on transient errors |
| --retry-delay <s> | Fixed delay between retries (disables backoff) |
| --retry-max-time <s> | Stop retrying after this many total seconds |
| --retry-all-errors | Retry on any error, not just transient (curl 7.71+) |
| --retry-connrefused | Also retry when the connection is refused (7.52+) |
In CI
A robust combination for a flaky endpoint is -fsS --retry 5 --retry-all-errors --retry-connrefused --max-time 120. The -f makes a final 5xx fail the step, --retry-all-errors covers DNS and connect hiccups, and --max-time bounds the whole thing. Check curl --version since --retry-all-errors needs 7.71.
Common errors in CI
If retries never happen on a connection refused, you are missing --retry-connrefused, since plain --retry does not cover that case before some versions. curl: option --retry-all-errors: is unknown means the runner curl is older than 7.71.