cache: hashFiles function throwing error.

We are facing issue with node caching today on ubuntu-18.04. Following is the error

 hashFiles('../../**/package-lock.json') failed. Fail to hash files under directory

This has been working for the past 2 years. However starting today morning we are facing this issue

   uses: actions/cache@v1
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-cache-${{ hashFiles('../../**/package-lock.json')}}
          restore-keys: |
            ${{ runner.os }}-node-cache-

Screenshot 2022-03-03 at 1 52 55 PM

24 hours back it was running as expected Screenshot 2022-03-03 at 2 39 34 PM

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 24 (6 by maintainers)

Commits related to this issue

Most upvoted comments

We also started running into this issue today. After enabling step debug logging, it seems that for us the error was caused by a permissions issue. Specifically, during the CI run, a folder was created by Docker within the workspace with permissions that meant that hashFiles could not search that folder for files which matched our search pattern. I assume that this failed silently before, but is now an error due to https://github.com/actions/runner/pull/1678.

We are able to resolve this either by making the pattern more concrete (e.g. instead of using **/*.cabal, we could use **/foo.cabal, but then we need to be careful about adding all package files explicitly now and in the future) or by moving the folder created by Docker outside the workspace.

In any case, I am wondering though if the solution implemented by https://github.com/actions/runner/pull/1678 could be improved. At least, it would be nice to have a better indication of what the error is without having to enable step debug logging. Perhaps the errors should be warnings instead? Or perhaps there should only be an error if hashFiles returns an empty string?

I resolved this by changing this:

      - uses: actions/cache@v2
        with:
          path: '**/node_modules'
          key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

to this:

      - uses: actions/cache@v2
        with:
          path: '/node_modules'
          key: ${{ runner.os }}-modules-${{ hashFiles('/yarn.lock') }}

In my case I’m using cypress-io/github-action and was getting the EACCES: permission denied error. I fixed it by running containers as user 1001

container:
  image: cypress/browsers:node14.17.0-chrome88-ff89
  options: --user 1001

According to this old version of the cypress-io/github-action README:

This issue is caused by the user not having the right permissions to the cache directory, and seems to only happen when using a docker container.

In order to fix this, you need to specify a specific user to run the container.

user 1001 is a special user within GitHub Actions which has the necessary permissions to write to /github/home/…

@Chrischuck Yes, if the cause is due to [Permission denied], you do not need to do anything. 👌🏿

If you want to see the cause of the hashFiles error, you need to enable debug logging. If you see [Permission denied] (example), my PR will automatically fix it.

However, since it has not been reviewed, it remains to be seen when a fix will be made… 😩

In our case it was caused because there was an access error during file matching.

##[debug][Error: EACCES: permission denied, scandir '/home/runner/work/xxx'] { 
##[debug] errno: -13, 
##[debug] code: 'EACCES', 
##[debug] syscall: 'scandir', 
##[debug] path: '/home/runner/work/xxx' 

To debug the issue you can manually run hashFiles by logging in to the self-hosted worker and evaluating (in the work directory)

$ patterns='src/**' node  ~/bin.2.288.1/hashFiles/index.js

In my case, hashFiles fails because of a dangling symlink that throws an Error: ENOENT. If it succeeds you get the hash printed to stdout, e.g.:

$ patterns=.github/cache-version node  ~/bin.2.288.1/hashFiles/index.js 
Match Pattern: .github/cache-version
::debug::followSymbolicLinks 'false'
::debug::followSymbolicLinks 'false'
::debug::implicitDescendants 'true'
::debug::omitBrokenSymbolicLinks 'true'
::debug::Search path '/var/home/agent-91/_work/talque/talque/.github/cache-version'
/var/home/agent-91/_work/talque/talque/.github/cache-version
Found 1 files to hash.
__OUTPUT__ae876d3c7f80bd4544e167f2dabe3af79d5a3e052c5ff4226cd95c03895fc700__OUTPUT__
undefined

And it clearly is reevaluated in the Post Run actions/cache@v2 step, because that is where it errors out for me. That makes zero sense at all; the cache key must be the one from the Run actions/cache@v2 step. Later there will typically be build artifacts that will be picked up by globs.

For me, specifying an absolute path in the key

      - uses: actions/cache@v2
        with:
          path: '/artifacts'
          key: cache-key-${{ hashFiles('/src/**') }}

just creates an empty key, i.e. cache-key- as if hashfiles returns the empty string. This is a self-hosted runner, in case it matters.

I see lots of projects linked on this issue that “fixed” this and now have keys that do not have any hash in them any more, this is going to be a cluster**** when they start changing their sources and keep downloading stale caches.

Really hashFiles should error out if there is a glob that does not match anything, or if there is a file that does not exist. Ideally with a sane error message that tells us what the whole glob was, including any prepended workspace paths. Hashfiles should never return the empty string.

Ours problem is **/composer.lock instead. I’m wondering if changing to composer.lock would cause any problem, since it will then only hash the composer.lock file in root folder, and not including those under vendors folder. I reckon it’s okay because if any of the composer.lock files are changed under vendors, then the main composer.lock under root folder should have changed first (lib versions, etc), right?

After discussing this internally, we think this is related to - https://github.com/actions/runner/pull/1678. Essentially hashFiles was previously failing silently but with the new runner version it will raise an Error instead.

You can also see this was the case in @moerishabh 's screenshot, where it shows:

key: Linux-node-cache-
restore-keys: Linux-node-cache-

Essentially, the hash was never getting computed + added to the key.

@moerishabh I think you can fix that by removing the relative paths of ../../. @Dragory I’m not exactly sure why yours is failing. Could you please enable step debug logging, re-run the workflow, and look at the extra debug output to see what error it shows?

@moerishabh Any reason why you are still using the old v1 version of API instead of v2? Regarding your problem- Can you try giving an absolute path for package-lock.json and avoid using ** as it may cause problems for subnested package-lock.json files inside node_modules ? or is it what you want ?