CircleCI Cache Restored Wrong Arch - Fix Cross-Executor Caches
A cache built on one executor is restored on a different OS/arch, so native binaries no longer match. Sharing a cache key across Linux/macOS, x86/arm, or different runtime versions restores incompatible compiled artifacts.
What this error means
After a cache hit the job fails with "exec format error", a Node/Python ABI mismatch, or a native module that "was compiled against a different version". It only happens on some executors because the cache came from another platform.
Error: Module did not self-register / exec format error
node_modules/.../binding.node: cannot execute binary file
(cache built on linux/amd64, restored on linux/arm64)Common causes
One cache key shared across architectures
A key without an arch/OS component lets an arm job restore an x86-built cache (or vice versa). Native .node/.so files are not portable.
Cache shared across runtime versions
Native modules are built against a specific Node/Python ABI. Restoring a cache built on a different runtime version yields ABI errors.
Caching compiled node_modules across executors
Caching built node_modules rather than the package manager cache makes the cache platform-specific and fragile across executor types.
How to fix it
Include OS/arch/runtime in the cache key
- restore_cache:
keys:
- deps-v1-{{ arch }}-{{ checksum ".node-version" }}-{{ checksum "package-lock.json" }}
- run: npm ci
- save_cache:
key: deps-v1-{{ arch }}-{{ checksum ".node-version" }}-{{ checksum "package-lock.json" }}
paths: [~/.npm]Cache the package manager cache, not compiled output
- Cache
~/.npm/~/.cache/pip, then reinstall to rebuild native modules per platform. - Add the runtime version to the key so ABI changes invalidate it.
- Use distinct key prefixes per executor when caches must differ.
How to prevent it
- Always include
{{ arch }}and the runtime version in cache keys. - Cache the package manager cache, not platform-specific compiled modules.
- Use separate keys per executor type to avoid cross-arch restores.