Skip to content
Latchkey

GitHub Actions hashFiles Returns Empty - Cache Key Has No Hash

hashFiles() returns an empty string when its glob matches nothing, so a key like deps-${{ hashFiles(...) }} becomes just deps-. Every run then shares one stale entry, or the cache never reflects real changes.

What this error means

The cache key in the logs has a trailing dash with no hash, and caching behaves oddly - either always hitting a stale entry or never updating when dependencies change.

.github/workflows/ci.yml
key: deps-${{ hashFiles('**/package-lock.json') }}
# resolves to "deps-" because no lockfile matched the glob

Common causes

Glob matches no files

hashFiles is relative to the workspace. A wrong path, a lockfile in a subdirectory, or a missing file makes the glob match nothing and return empty.

hashFiles runs before checkout

If the cache step runs before actions/checkout, the files are not present yet, so the glob matches nothing.

How to fix it

Point the glob at real files after checkout

Use a glob that matches the committed lockfile, and ensure checkout runs first.

.github/workflows/ci.yml
- uses: actions/checkout@v4
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ hashFiles('**/package-lock.json') }}

Verify the hash is non-empty

  1. Echo the computed key and confirm a real hash follows the prefix.
  2. Adjust the glob to the actual lockfile location (root vs subdirectory).
  3. Place the cache step after checkout so the files exist.

How to prevent it

  • Confirm hashFiles globs match committed files in the workspace.
  • Run cache steps after actions/checkout.
  • Log the cache key when changing the hashFiles pattern.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →