SwiftPM stale .build / SourcePackages cache in CI
Caching .build (or DerivedData/SourcePackages) speeds up SPM builds, but a cache restored across a dependency change, toolchain change, or platform change can contain modules that no longer match, producing confusing build or module errors.
What this error means
After restoring an SPM cache, builds fail with module-built-for mismatches, "no such module", or stale resolved pins that do not match the current Package.swift.
error: could not build module 'Networking'
note: the module cache at '.build/.../ModuleCache' was built for a different toolchainCommon causes
The cache key ignores the dependency or toolchain version
A cache keyed only on the OS restores .build/SourcePackages from a different Package.resolved or Swift version, so cached modules are wrong.
A platform or architecture change invalidated artifacts
Switching runner architecture or deployment target while reusing a cache mixes incompatible compiled modules.
How to fix it
Key the cache on the resolved file and toolchain
- Include
Package.resolvedand the Swift/Xcode version in the cache key. - Restore only when both match, so stale artifacts are not reused.
- On a mismatch, build fresh instead of reusing.
- uses: actions/cache@v4
with:
path: .build
key: spm-${{ runner.os }}-${{ hashFiles('Package.resolved') }}Clear the cache when artifacts are mismatched
When a build shows module-mismatch errors, remove the cached build directory and rebuild.
rm -rf .build
swift buildHow to prevent it
- Key SPM caches on
Package.resolvedplus the Swift/Xcode version. - Invalidate the cache on architecture or platform changes.
- For Xcode, cache the cloned SourcePackages directory with a matching key.