Skip to content
Latchkey

sbt "unresolved dependency" in CI

sbt asked a resolver for an artifact and got nothing back. Either the coordinates are wrong, the resolver is missing, or the network call to fetch the JAR failed mid-build.

What this error means

Dependency resolution aborts with unresolved dependency: group#artifact;version: not found, often followed by the list of resolvers sbt tried. When the coordinates are real, the failure is usually a transient network or registry hiccup.

sbt
[error] (update) sbt.librarymanagement.ResolveException: Error downloading com.example#widget_2.13;1.4.0
[error]   Not found
[error]   download failed: com.example#widget_2.13;1.4.0!widget_2.13.jar

Diagnose it: which runtime is on PATH?

Terminal
which -a <runtime>
<runtime> --version
cat .tool-versions .nvmrc .ruby-version .python-version 2>/dev/null

Common causes

Wrong coordinates or missing Scala suffix

A Scala library is published as widget_2.13, not widget. Omitting the %% operator (which appends the binary version) leaves sbt looking for an artifact that does not exist.

A private resolver is not configured

If the artifact lives in a private Maven repo, CI needs the resolver and credentials. Without them, sbt only checks Maven Central and reports the module as not found.

Transient fetch failure

The coordinates resolve but the JAR download times out or the registry returns 5xx. The same build passes on a re-run.

How to fix it

Confirm the coordinates and operator

  1. Use %% for Scala libraries so sbt appends the binary version, and % only for plain Java JARs.
  2. Verify the exact group, artifact, and version exist on the published index.
  3. Run sbt update locally to reproduce before pushing.

Add the private resolver and credentials

Declare the resolver and supply credentials from CI secrets, not committed files.

build.sbt
resolvers += "Internal" at sys.env("REPO_URL")
credentials += Credentials(
  "Repo", "repo.example.com",
  sys.env("REPO_USER"), sys.env("REPO_TOKEN"))

Re-run if the download itself failed

A bare Not found on valid coordinates is usually transient. On Latchkey managed runners, self-healing auto-retries transient fetch failures so a one-off registry blip does not fail the job.

How to prevent it

  • Pin versions and commit a reproducible dependency set.
  • Keep resolver URLs and credentials in CI secrets.
  • Cache the Coursier/Ivy directory to reduce network fetches.

Frequently asked questions

What causes sbt "unresolved dependency" in CI?
There are 3 common causes: wrong coordinates or missing scala suffix, a private resolver is not configured, and transient fetch failure. A Scala library is published as widget_2.13, not widget.
How do I fix sbt "unresolved dependency" in CI?
There are 3 fixes depending on which cause you have: confirm the coordinates and operator, add the private resolver and credentials, and re-run if the download itself failed. Work through them in order, since the first is the most common.
What does sbt "unresolved dependency" in CI actually mean?
Dependency resolution aborts with unresolved dependency: group#artifact;version: not found, often followed by the list of resolvers sbt tried.
How do I stop sbt "unresolved dependency" in CI happening again?
Pin versions and commit a reproducible dependency set. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card