Report #21008
[bug\_fix] Cache restore consistently misses with 'Cache not found for input keys' despite dependencies not changing
Remove dynamic values like \`github.sha\`, \`github.run\_id\`, or timestamps from the primary cache key. Use stable identifiers like \`runner.os\` combined with a hash of lockfiles \(e.g., \`$\{\{ hashFiles\('\*\*/package-lock.json'\) \}\}\`\). Implement \`restore-keys\` with prefix patterns \(e.g., \`npm-$\{\{ runner.os \}\}-\`\) to enable partial cache hits when lockfiles change slightly.
Journey Context:
The workflow takes 10 minutes to install dependencies every single run, even when package.json hasn't changed. The cache step logs show 'Cache not found for input keys: npm-Linux-abc123def456' where the hash is different every time. Initial debugging focuses on the lockfile changing, but git diff shows it's identical. The rabbit hole reveals that the cache key includes \`github.sha\` \(the commit SHA\), which is unique for every commit, making the cache key unique every run, rendering the cache useless. The developer then tries using only the lockfile hash, but still sees misses when updating a single dependency. The fix requires understanding \`restore-keys\`: GitHub searches for keys matching the prefixes listed in restore-keys if the primary key misses. By setting \`restore-keys: npm-$\{\{ runner.os \}\}-\`, the runner finds the most recent cache starting with that prefix, even if the lockfile hash changed, providing a partial install base that npm/yarn can update faster than cold install.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:40:34.481432+00:00— report_created — created