The Cypress binary is missing in CI
When a CI job reports that the Cypress binary is missing, it is not a download failure: the npm package installed correctly, and the binary is either sitting somewhere else on the same disk or was never carried between two jobs. Cypress keeps the binary in a global cache outside node_modules, so restoring node_modules without that cache produces this message every time.


What this error means
The message names a path, and the path is the whole diagnosis. Cypress prints where it expected the binary, then lists the two reasons it knows about: caching node_modules without caching the binary folder, and installing in an earlier step whose filesystem did not survive. Below that it offers the fix in one line, cypress install. There is a second wording for the same condition. Cypress chooses its message from its own CI detection, so a laptop gets "No version of Cypress is installed in" for the identical situation, which is why this sentence turns up in bug reports about CI and almost never in ones about local runs. The run below is the failure with nothing substituted: the real package from the real registry, the real binary really downloaded, and one environment variable different between the step that installs and the step that runs. The binary is on disk the whole time, under the other folder, and the log prints its size just before the failure.
The cypress npm package is installed, but the Cypress binary is missing.
We expected the binary to be installed here: /home/runner/cypress-cache-run/16.1.0/Cypress/Cypress
Reasons it may be missing:
- You're caching 'node_modules' but are not caching this path: /home/runner/cypress-cache-run
- You ran 'npm install' at an earlier build step but did not persist: /home/runner/cypress-cache-runReproduced on a Latchkey runner
install step CYPRESS_CACHE_FOLDER=/home/runner/cypress-cache-install
cypress package 16.1.0, install cache holds version 16.1.0 at 819M
test step CYPRESS_CACHE_FOLDER=/home/runner/cypress-cache-run
The cypress npm package is installed, but the Cypress binary is missing.
We expected the binary to be installed here: /home/runner/cypress-cache-run/16.1.0/Cypress/Cypress
Reasons it may be missing:
- You're caching 'node_modules' but are not caching this path: /home/runner/cypress-cache-run
- You ran 'npm install' at an earlier build step but did not persist: /home/runner/cypress-cache-run
Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.
Alternatively, you can run 'cypress install' to download the binary again.
https://on.cypress.io/not-installed-ci-error
----------
Platform: linux-x64 (Ubuntu - 24.04.4 LTS)
Cypress Version: 16.1.0
cypress verify exited 1, now running the fix its own message names
[COMPLETED] [10:26:25] Finished Installation /home/runner/cypress-cache-run/16.1.0Where Cypress actually puts the binary
The npm package is a small command line wrapper. The application it runs is a separate download, unzipped into a global cache that is shared by every project on the machine, which is what makes it survivable between runs and also what makes it easy to lose.
| Platform | Default binary cache | What to cache in CI |
|---|---|---|
| Linux | ~/.cache/Cypress | That folder, keyed on the Cypress version |
| macOS | ~/Library/Caches/Cypress | Same, and note the runner user differs from a laptop |
| Windows | /AppData/Local/Cypress/Cache | Same, with the path style of the runner |
| Any, overridden | Whatever CYPRESS_CACHE_FOLDER says | The same value in every job that touches Cypress |
Common causes
node_modules was cached and the binary folder was not
The reason Cypress lists first in its own error, and the most common one in practice. A cache key built from the lockfile restores the package, the postinstall step never runs because npm sees nothing to do, and the download that would have fetched the binary is skipped along with it. The package and the binary are two artifacts, and only one of them came back.
The install job and the test job disagree about the cache folder
Either because CYPRESS_CACHE_FOLDER is set in one and not the other, or because they resolve different homes. A step with container: has a different HOME from the runner user, so the same default expands to a different absolute path, and a cache restored outside the container is not where the container looks.
The binary was never downloaded, by design
Base images are often built with CYPRESS_INSTALL_BINARY=0 to keep them small, which Cypress documents as skipping the download entirely. That is a reasonable choice, and it means something later has to supply the binary. When that step is missing, or is a cache restore that misses, this message is the result.
The install ran as a different user than the run
An install under sudo, or in a container as root, writes the cache into that user's home. The test step runs as the ordinary runner user, resolves its own home, and finds nothing. The message looks identical to the caching cause and is fixed differently, so it is worth printing the resolved path in both steps before guessing.
How to fix it
Cache the binary folder, not node_modules
- Set
CYPRESS_CACHE_FOLDERto a path inside the workspace so every step, container or not, resolves the same absolute path. - Key the cache on the Cypress version, because the folder holds one directory per version and a stale key wastes the restore.
- Cache your package manager's store separately, and let the install run on every job.
env:
CYPRESS_CACHE_FOLDER: ${{ github.workspace }}/.cypress-cache
steps:
- uses: actions/cache@v6
with:
path: ${{ github.workspace }}/.cypress-cache
key: cypress-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
- run: npx cypress runRun the command the error names
When the package is present and the binary is not, cypress install downloads and unzips it into the folder the current environment resolves. It is safe to run unconditionally: with the binary already in place it is close to a no-op, and it removes a class of cache misses from your pipeline in one line.
npx cypress install
npx cypress cache list --sizePrint the path from both steps before changing anything
The fastest way to tell the four causes apart is to make both steps say where they are looking. If the two lines differ, it is a path problem. If they match and the folder is empty, the download never happened or the cache restore missed.
- run: |
echo "HOME=$HOME"
echo "cache=${CYPRESS_CACHE_FOLDER:-$HOME/.cache/Cypress}"
ls -la "${CYPRESS_CACHE_FOLDER:-$HOME/.cache/Cypress}" || trueKeep the binary in the image if you build one
For a container job, install the binary in the image and set the cache folder to the location you installed it into, so the container is self-sufficient and no cache restore is on the critical path. If you deliberately build with the download skipped, add the install to the entrypoint instead of hoping a cache covers it.
ENV CYPRESS_CACHE_FOLDER=/opt/cypress-cache
RUN npm ci && npx cypress install && npx cypress cache listWhat the recorded run shows, and what no runner can do about it
The install wrote 819M into one folder and the test step looked in another, on the same machine, seconds apart. The step then ran the fix Cypress names in its own error text, and the binary landed in the folder that had been empty.
This is the failure class where a retry is worthless, and it is worth being explicit about that, because most of the pages in this cluster are about the opposite. A cache path that does not hold the binary does not hold it on the second attempt either. Nothing in the path is transient, the command is deterministic, and the only thing that changes the outcome is changing the configuration. See how self-healing works for the line a managed runner draws between a failure it can act on and a misconfiguration it should hand back to you.
How to prevent it
- Set
CYPRESS_CACHE_FOLDERto an absolute workspace path in one place, at workflow level. - Cache that folder keyed on the Cypress version, and never cache
node_modules. - Run
npx cypress installafter the dependency install, so a cache miss costs a download rather than a red build. - Print the resolved cache path in CI, so the next occurrence is diagnosed from the log rather than from guesses.
Frequently asked questions
Why is the Cypress binary missing after npm ci?
npm ci only installs the package, and the binary comes from the postinstall step that downloads it into a global cache. If node_modules was restored from a cache, npm has nothing to install and the postinstall never runs, so the binary is never fetched. Cache the Cypress cache folder instead, and run npx cypress install after the dependency install.What should CYPRESS_CACHE_FOLDER be set to in GitHub Actions?
~/.cache/Cypress on Linux, which is fine until a container step brings its own home directory and quietly resolves somewhere else.Does cypress install download the binary again every run?
npx cypress cache list --size reports what is in the folder if you want the step to be visible in the log.Why does the error say the binary is missing when it is on disk?
Related guides
References
- Cypress documentation: continuous integration and caching the binary
- Cypress documentation: advanced installation, cache folder and environment variables
- cypress-io/cypress#21022: the cypress npm package is installed, but the Cypress binary is missing
- cypress-io/github-action#1246: the same failure through the official action
- GitHub Actions documentation