yarn network timeout ci: two Yarns, two different fixes
A yarn network timeout ci failure comes from one of two completely different programs that happen to share a name, and the first job is to work out which one printed your log. Yarn 1 prints friendly sentences and a stack trace, Yarn 4 prints numbered codes and an indented field list, and almost every setting people recommend for one of them does not exist in the other.

What this error means
Yarn 1 announces the trouble before it fails, repeating a line about your network connection once per retry, and then ends with an error Error: line carrying the URL and a code such as ETIMEDOUT. Yarn 4 prints nothing until it has finished retrying, then emits a YN0035 block with the response code, the method, the URL and the retry count it used. The two blocks below were produced in containers running yarn 1.22.22 and yarn 4.18.0 against servers we control: an unroutable address for the timeout, and a local 503 responder for the refusal. This page carries no reproduction on a Latchkey runner, so the hosts are ours.
info There appears to be trouble with your network connection. Retrying...
[three more of the same notice, elided]
error Error: https://192.0.2.1/is-odd: ETIMEDOUTTell the two apart in one line of log
If the log has lines beginning with info, warning and error in lower case, and ends in a Node stack trace, it is Yarn 1. If every line opens with an arrow glyph and a code like YN0000 or YN0035, it is Yarn 2 or later, which in practice means Yarn 4. Everything after this point depends on that answer.
The Yarn 4 form for the same class of failure is a block rather than a sentence, and it is considerably more useful because it tells you how many retries it performed. Against a registry answering 503, with default settings, it reported three.
➤ YN0035: │ is-odd@npm:3.0.1: The registry appears to be down (using a local cache might have protected you against such outages)
➤ YN0035: │ Response Code: 503 (Service Unavailable)
➤ YN0035: │ Request Method: GET
➤ YN0035: │ Request URL: http://mirror503:8899/is-odd
➤ YN0035: │ Request Retry Count: 3 (can be increased via httpRetry)| Yarn 1.22.22 | Yarn 4.18.0 | |
|---|---|---|
| Message on failure | error Error: <url>: ETIMEDOUT | A YN0035 block with the response code |
| Attempts before giving up | Five, measured against a 503 responder | Four, measured: one try plus three retries |
| Timeout setting | --network-timeout, in milliseconds, default 30 seconds | httpTimeout, default 1m |
| Retry setting | Not exposed on the command line | httpRetry, default 3 |
| Concurrency default | 8 | 50 |
| Plain HTTP registry | Allowed | Refused unless the host is whitelisted |
Common causes
The registry or the path to it stalled
A socket that connects and then goes quiet, a proxy that accepts and does not forward, or a registry under enough load that it stops answering. Yarn 1 reports this as ETIMEDOUT with the URL; Yarn 4 reports a request that ran out of time rather than a response code, which is the same distinction other package managers make.
One job is making far more requests than the registry expects
Yarn 4 sets networkConcurrency to 50 by default, and a matrix multiplies that across jobs. An internal registry that is comfortable with a developer laptop can start dropping connections when a CI fleet arrives, and the result looks like a timeout rather than like throttling.
Nothing is cached, so every job re-fetches the whole tree
An install with a cold cache makes one request per package. That is the exposure, and it is entirely avoidable. Yarn 4 in particular is designed around a checked in or cached offline mirror, and the YN0035 message says so directly by noting that a local cache might have protected you.
A migration left Yarn 1 settings in a Yarn 4 repository
A --network-timeout flag in a workflow, or a .yarnrc that Yarn 4 does not read, quietly does nothing. In our experience this is why a team reports that raising the timeout did not help: the value never reached the program that was timing out.
How to fix it
On Yarn 4, set httpRetry and httpTimeout in .yarnrc.yml
- Put both settings in the repository so every machine and every runner agrees, rather than passing flags in one workflow.
- Raise
httpRetrybefore you raisehttpTimeout. A registry that is briefly unavailable needs more attempts, not one longer attempt. - Confirm the change took effect by reading the retry count in the next YN0035 block, which prints the number it used.
httpRetry: 5
httpTimeout: 120000
networkConcurrency: 16On Yarn 1, raise the network timeout and accept the fixed retries
The two network levers Yarn 1 exposes on the command line are the timeout and the concurrency. NETWORK_TIMEOUT in its constants is 30 seconds and --network-timeout overrides it, which helps a slow link and does nothing for an unreachable host. NETWORK_CONCURRENCY is 8, so passing --network-concurrency 8 changes nothing; go below it or leave it out. The retry count is not configurable at all, so if five attempts are not enough the answer is to make fewer requests.
yarn install --frozen-lockfile --network-timeout 120000 --network-concurrency 4Cache the right directory for your version
The two versions keep their caches in different places, which is another thing a migration gets wrong. Cache the one your version actually uses, keyed on the lockfile, and most installs stop touching the registry at all.
- uses: actions/cache@v4
with:
path: .yarn/cache
key: yarn4-${{ runner.os }}-${{ hashFiles('yarn.lock') }}Put the registry behind TLS before moving to Yarn 4
Yarn 4 declines plain HTTP registries by default, and the whitelist exists for situations you cannot change rather than as a normal configuration. Doing the TLS work as part of the migration avoids a failure that arrives on the first install and looks like a network problem.
unsafeHttpWhitelist:
- registry.internal.example.comWhat each version actually retried
Counting requests at the server settles what the logs only imply. Yarn 4.18.0 with default settings sent four requests for the package before failing, and reported a retry count of three, which matches its documented httpRetry default. Setting httpRetry to zero produced exactly one request, and the block then read Request Retry Count: 0, so the field is reporting the setting rather than a fixed string.
Yarn 1.22.22 sent five requests to the same server and printed four of its retry notices along the way. That matches maxRetryAttempts = 5 in its request manager rather than any setting, and yarn --help offers --network-concurrency and --network-timeout but nothing for retries, so the number really is out of reach from the command line.
Yarn 1 also picks its sentence by what went wrong, and the wording is diagnostic. Against an unroutable address it repeats "There appears to be trouble with your network connection." Against the 503 responder it repeats a different sentence, one that names the npm registry rather than your connection and carries a parenthetical for the status code that Yarn 1 leaves unfilled, and the run ends in a ResponseError: Request failed "503 Service Unavailable" rather than a socket error. If your Yarn 1 log names the registry rather than your connection, the registry answered.
This is the practical difference between the two. On Yarn 4 the retry budget is yours to set. On Yarn 1 it is not, so the only levers you have are the timeout, the concurrency and whether the request has to happen at all.
Yarn 4 refuses plain HTTP, which reads like a network failure
One failure that gets filed under network timeouts is not one. Pointing Yarn 4 at an http:// registry without whitelisting the host produced ➤ YN0081: │ is-odd@npm:3.0.1: Unsafe http requests must be explicitly whitelisted in your configuration (mirror503) and stopped. No request reached the server, so nothing timed out, and the whole run finished in sixteen milliseconds, but the job failed at the same point in the install and the log looks similar at a glance.
If you are moving an internal registry from Yarn 1 to Yarn 4, this will be the first thing you hit. Either put the registry behind TLS, which is the right answer, or add the host to the whitelist in .yarnrc.yml deliberately.
npmRegistryServer: "https://registry.internal.example.com"
httpRetry: 5
httpTimeout: 120000Why this page has no runner reproduction
Both failures need a registry that misbehaves on demand. An unroutable address gives a genuine socket timeout and a server answering 503 gives a genuine refusal, and both run in a container in seconds. A runner job would have produced the same two messages with a different hostname in them, which is not more evidence, and it would have cost minutes to get.
Counting the requests each Yarn sent is the part that mattered most here, and that needs a server you own on the other end. There is no entry for this slug in content/heal-evidence.mjs, so this page is not marked healable and makes no claim that Latchkey repairs it.
How to prevent it
- Decide which Yarn the repository is on and delete the settings that belong to the other one.
- Cache
.yarn/cacheon Yarn 4 or the Yarn 1 cache directory on Yarn 1, keyed on the lockfile. - Set
networkConcurrencyfor CI when the registry is one you operate. - Move internal registries behind TLS rather than whitelisting plain HTTP and forgetting about it.
Frequently asked questions
How many times does Yarn retry a failed registry request?
httpRetry setting, and prints the count it used in the YN0035 block; we counted four requests reaching the server, and one request after setting httpRetry to zero. Yarn 1 attempts five times in total, which we also counted, and does not expose that number as a flag, because maxRetryAttempts is fixed in its request manager.Does --network-timeout work in Yarn 4?
httpTimeout, which defaults to one minute and is set in .yarnrc.yml. A workflow that still passes the old flag after a migration is changing nothing, which is a common reason a timeout increase appears to have no effect.What does YN0035 mean in a Yarn install?
Why does Yarn 4 refuse my internal registry over http?
unsafeHttpWhitelist only when you genuinely cannot.Related guides
References
- Yarn configuration reference: httpRetry, httpTimeout and networkConcurrency
- yarnpkg/berry: httpUtils.ts, where the YN0035 block is assembled
- yarnpkg/yarn: constants.js, the 30 second NETWORK_TIMEOUT in Yarn 1
- yarnpkg/yarn: request-manager.js, the fixed five attempt maximum
- Node.js documentation
- npm CLI documentation
- GitHub Actions documentation