CIPatch

GitHub Actions cache not working

A cache that never hits is worse than none: you pay the upload and still wait for a cold install every run.

1. There is no cache at all

The setup actions ship caching, and it is off unless you ask for it:

      - uses: actions/setup-node@v4
        with:
          node-version: 20
+         cache: npm

Equivalent inputs exist for setup-python (pip, poetry, pipenv) and setup-java (gradle, maven). This is the most common cause and the cheapest fix.

2. No lockfile, so there is nothing to key on

cache: npm hashes your lockfile to build the key. Without package-lock.json the action cannot compute a key and caching silently does nothing. Commit the lockfile. The same applies to poetry.lock, Pipfile.lock, yarn.lock and pnpm-lock.yaml.

3. A key with something volatile in it

- key: ${{ runner.os }}-node-${{ github.run_id }}
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

run_id, run_number and timestamps change on every run, so the key never matches and the cache is rebuilt every time. A key should be a function of the inputs, not of the run.

4. A monorepo looking in the wrong place

In a workspace repository the lockfile is often not at the root. Point the action at it:

        with:
          cache: npm
+         cache-dependency-path: apps/web/package-lock.json

Without this, the key hashes a file that does not exist and the cache never hits.

5. Expecting a hit on a different branch

Caches are scoped to the branch that created them. A pull request can restore the base branch's cache, but the base branch cannot restore a pull request's cache, and a brand-new branch starts cold. Also worth knowing: caches not read for seven days are evicted, and a repository has a total cache budget of about 10 GB, after which older entries are removed. A cache that worked last month may have been evicted rather than broken.

Confirm it actually worked

Look for a Cache restored line in the step output, and check that the install step got materially shorter. Then measure over at least ten comparable runs: a cold first run is expected and is not a regression.

Check your own repository in about a minute.

CIPatch reads your workflow and lockfiles and reports whether a safe cache is missing or misconfigured. The scan is read-only, needs no account for the first repository, and changes nothing.

Scan a public repository · Cost calculator