Skip to content
Latchkey

actions/cache cross-OS cache restore mismatch in CI

A cache key that omits runner.os lets a Linux cache restore onto Windows or macOS (and vice versa). The restored archive holds platform-specific binaries and path layouts that do not work on the other OS, causing native-module errors or tar failures.

What this error means

After a cache hit, the build fails with native module ABI errors, "is not a valid Win32 application", missing binaries, or a tar error, because the restored cache came from a different operating system.

actions/cache
Cache restored from key: deps-7f3a9c
Error: \\?\D:\a\app\node_modules\fsevents\build\Release\fse.node is not a valid Win32 application.

Common causes

The cache key has no OS component

A key like deps-${{ hashFiles(...) }} is shared across all matrix OSes, so whichever job saves first poisons the others with its platform binaries.

Restore-keys prefix matches across OSes

A shared restore-keys prefix without runner.os lets a prefix hit pull another OS's cache.

How to fix it

Always include runner.os in key and restore-keys

  1. Add ${{ runner.os }} to both key and every restore-keys prefix.
  2. Re-run so each OS only ever restores its own cache.
  3. Confirm the native errors disappear after the keys are OS-scoped.
.github/workflows/ci.yml
key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
  deps-${{ runner.os }}-

Add arch too when runners differ

On mixed architectures (for example arm64 vs x64 macOS), add ${{ runner.arch }} so a cache never crosses CPU architectures either.

How to prevent it

  • Scope every cache key by runner.os (and runner.arch when relevant).
  • Never share a dependency cache across operating systems.
  • Keep matrix legs isolated with distinct key prefixes.

Related guides

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