## TL;DR
Exit code 7 means the TCP connection never established at all - check DNS, the firewall, or whether the service is even listening. Exit code 28 means the connection (or DNS/TLS stage) started but nothing finished before the deadline - raise the timeout or look at server slowness. The number tells you exactly where in the handshake it broke, so read it before retrying blindly.

```text
curl "(28) timeout" vs "(7) failed to connect": what each means
```

## Steps

1. Re-run the exact curl with verbose output to see which stage stalls.
   Expected: with code 7 you see the connect attempt fail immediately; with code 28 you see it hang after "connected" or during the TLS handshake.

2. For code 7, confirm DNS resolves and the port is reachable from this host.
   Expected: the hostname resolves to an IP and a basic port test shows the port open; if not, you have a DNS or firewall problem, not a curl problem.

3. For code 28, separate the two deadlines: bump only --connect-timeout first, then only --max-time.
   Expected: if raising --connect-timeout fixes it, the handshake was slow; if only --max-time helps, the server is slow to answer.

4. Compare the same request from a known-good host or network.
   Expected: works elsewhere means the fault is local network or firewall; fails everywhere means the server side is the problem.

5. Once classified, encode the right retry policy: retry with backoff on 28s, alert a human on persistent 7s.
   Expected: transient slowness self-heals; dead endpoints page instead of burning retries.

## Use this when
- curl exits 7 or 28 in a script, CI job, cron, or agent tool call
- deciding whether a failed request deserves a retry or an alert
- writing retry logic around HTTP calls made with curl

## Not for this skill when
- the failure comes from a browser fetch or an HTTP library (requests, urllib, axios) rather than the curl binary
- curl got an HTTP response and the status was 5xx - that is a server error, not a connection error
- DNS tooling itself (dig, nslookup) is failing - fix DNS first

## Variant phrasings
- curl error 28: connection timed out
- curl: (7) Failed to connect - couldn't connect to host
- curl (28) vs (7): which one means the server is slow
- curl timeout vs connection refused in shell scripts

## Why it happens
Code 7 fires when the OS connect call fails: SYN packets unanswered, actively refused, or no route. Code 28 fires when any phase (DNS, TCP connect, TLS handshake, or waiting for response bytes) exceeds its deadline. One is "nobody home", the other is "somebody home but silent".

## Edge cases
- Code 28 during the TLS handshake specifically points at a slow or overloaded TLS terminator, not the app
- A proxy in the middle can turn a refused upstream into a 7 or a hang into a 28 - test direct to be sure
- --max-time covers the whole operation including slow downloads; a huge response can 28 on an otherwise healthy server
- DNS slowness counts toward the timeout and surfaces as 28, which looks like server slowness but is not

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_kiKYNsCm_QLtTXpaOZj3nQ
