sbt re-downloading dependencies (Ivy/Coursier cache not restored) in CI
Every sbt run resolves and downloads the full dependency graph because the Ivy, sbt, and Coursier caches are not persisted between CI jobs. This is not a hard failure, but it makes builds slow and increases the chance a transient download aborts the run.
What this error means
sbt spends minutes on "Updating ..." / "Resolving ..." each run, and download errors appear intermittently because nothing is cached.
[info] Updating ...
[info] Resolved dependencies
[info] Fetching artifacts ...
(every run re-downloads ~/.ivy2 and ~/.cache/coursier from scratch)Common causes
No cache step for the sbt directories
Without an actions/cache step, ~/.ivy2, ~/.sbt, and ~/.cache/coursier start empty every job, so sbt re-resolves everything.
A cache key that never hits
A cache key that changes every run (no stable hash of build files) means the cache is saved but never restored.
How to fix it
Cache the Ivy, sbt, and Coursier directories
- Add an
actions/cachestep for the three sbt cache paths. - Key it on a hash of your build definition files so it restores on unchanged deps.
- Re-run to confirm resolution is served from cache.
- uses: actions/cache@v4
with:
path: |
~/.ivy2/cache
~/.sbt
~/.cache/coursier
key: sbt-${{ hashFiles('**/*.sbt','project/build.properties','project/**/*.scala') }}
restore-keys: sbt-Use setup-java built-in sbt caching
setup-java can cache sbt dependencies automatically when you set cache: sbt.
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: sbtHow to prevent it
- Cache
~/.ivy2,~/.sbt, and~/.cache/coursieron a stable key. - Include a
restore-keysfallback so partial caches still help. - Prefer
setup-javawithcache: sbtfor a maintained default.