/개발/6 Causes of Maven "Could not resolve dependencies" Build Failures and How to Fix Them with settings.xml
DevelopmentMaven 빌드오류Could not resolve dependencies

6 Causes of Maven "Could not resolve dependencies" Build Failures and How to Fix Them with settings.xml

Fix Maven "Could not resolve dependencies" and "Failed to execute goal" errors. Diagnose six causes—internal Nexus mirrors, proxies, PKIX, a corrupted .m2 cache, and more—in five minutes with copy-paste commands and settings.xml examples.

6 Causes of Maven "Could not resolve dependencies" Build Failures and How to Fix Them with settings.xml

6 Causes of Maven "Could not resolve dependencies" Build Failures and How to Fix Them with settings.xml

If a build that worked yesterday suddenly broke

You probably landed here after copying that red console line—Failed to execute goal ... Could not resolve dependencies—straight into a search engine. Short version: that message only reports the result ("couldn't fetch a dependency"). The real cause is hiding a few lines below it.

This happens a lot on locked-down networks with an internal Nexus/Artifactory, a corporate proxy, and a private CA—even when you didn't change a single line of code. This post is Maven-only. We'll pinpoint and recover from the failure in about five minutes using just the mirror/proxy/server tags in settings.xml, the ~/.m2 layout, and a few mvn flags.

Scope: Maven CLI, settings.xml, and the local repository (.m2). We don't cover IDE-embedded builds or other build tools.

Read the error properly first — find the real cause with mvn -X

The most common mistake is staring at the last Failed to execute goal line and giving up. That line always looks the same. What you actually need is the Caused by or Could not transfer artifact line above it.

Turn on debug logging and run it again.

Bash
# 전체 통신/저장소 접근 로그까지 출력
mvn -X clean install

With mvn -X, Maven prints which repository it tried, which URL it hit, and why it failed. Which of the keywords below shows up is your branch point.

Phrase in the logMapped causeOne-line meaning
Could not transfer artifact ... Connection refused / timed out② Proxy/firewall / ① Wrong mirror URLCan't reach the repository at all
PKIX path building failed / unable to find valid certification path③ Private-CA SSL failureTLS handshake rejected
Could not find artifact ...:jar:1.2.3 in central (404)⑤ Bad version / SNAPSHOT never deployedReached the repo, but that version isn't there
Failed to read artifact descriptor / mention of .lastUpdated④ Corrupted local cacheStuck on a broken cache entry
Cannot access ... in offline mode⑥ Misused -o flagOffline mode, but a new dependency is required

If you suspect a conflict, start with the dependency tree.

Bash
# 전체 의존성 트리
mvn dependency:tree

# 특정 라이브러리가 어디서 끌려오는지, 버전 충돌이 어떻게 정리됐는지 추적
mvn dependency:tree -Dverbose -Dincludes=org.springframework:spring-core

Cause ① Misconfigured internal Nexus/Artifactory mirror in settings.xml

If you see Connection refused and the URL is your internal Nexus (nexus.company.co.kr) rather than Maven Central, it's almost certainly a mirror misconfiguration in settings.xml. Typical triggers: Nexus is down for maintenance, the URL changed, or credentials expired.

Open ~/.m2/settings.xml and check what <mirrorOf> points at. Mirroring only central vs. mirroring * (everything) behaves completely differently.

XML
<!-- ~/.m2/settings.xml : 사내 Nexus 미러 + 인증 예제 -->
<settings>
  <servers>
    <!-- mirror의 id와 반드시 동일해야 인증이 적용됨 -->
    <server>
      <id>company-nexus</id>
      <username>${env.NEXUS_USER}</username>  <!-- 평문 대신 환경변수 권장 -->
      <password>${env.NEXUS_PASS}</password>
    </server>
  </servers>

  <mirrors>
    <mirror>
      <id>company-nexus</id>           <!-- server의 id와 일치 -->
      <name>Company Nexus</name>
      <url>https://nexus.example.co.kr/repository/maven-public/</url>
      <mirrorOf>*</mirrorOf>           <!-- 모든 저장소 요청을 Nexus로 우회 -->
    </mirror>
  </mirrors>
</settings>

The key point: the <server> id and the <mirror> id must match exactly, or the auth header never gets attached. If you get 401/403, suspect an id mismatch or an expired password first.

Cause ② Corporate proxy/firewall blocking Maven Central

If <mirrorOf> is only central, so Maven has to go out to Maven Central directly, and you get Connection timed out, the corporate firewall is likely blocking you because you didn't go through the proxy. Diagnose the block first.

Bash
# 프록시 없이 직접 닿는지 확인 (timeout이면 차단)
curl -I https://repo.maven.apache.org/maven2/

# 프록시를 거치면 되는지 확인
curl -I -x http://proxy.example.co.kr:8080 https://repo.maven.apache.org/maven2/

If you get a 200 through the proxy, register the proxy in settings.xml.

XML
<!-- ~/.m2/settings.xml : 프록시 설정 예제 -->
<settings>
  <proxies>
    <proxy>
      <id>company-proxy</id>
      <active>true</active>             <!-- false면 무시됨, 켜는 걸 잊지 말 것 -->
      <protocol>http</protocol>
      <host>proxy.example.co.kr</host>
      <port>8080</port>
      <username>proxyUser</username>    <!-- 인증 프록시일 때만 -->
      <password>proxyPass</password>
      <!-- 사내 Nexus는 프록시 제외(직접 접속) -->
      <nonProxyHosts>nexus.example.co.kr|localhost|127.0.0.1</nonProxyHosts>
    </proxy>
  </proxies>
</settings>

If you omit <nonProxyHosts>, Maven will try to send even internal Nexus traffic through the external proxy and fail again. Also note that Maven Central blocks HTTP and allows HTTPS only, so any leftover http://...central URLs in old configs need to be changed to https://.

Cause ③ PKIX/SSL handshake failure from a private CA

If you see PKIX path building failed or unable to find valid certification path to requested target, it's an SSL trust problem. The internal proxy/Nexus presents a cert signed by a private CA that isn't in the JDK trust store (cacerts), so the handshake is rejected. This is the fastest-growing case as more teams adopt zero-trust and air-gapped networks.

The core fix is importing the private CA certificate into the JDK.

Bash
# 사내 CA 인증서를 JDK 신뢰 저장소에 등록
keytool -import -trustcacerts -alias company-ca \
  -file company-ca.crt \
  -keystore "$JAVA_HOME/lib/security/cacerts" \
  -storepass changeit

Certificate extraction for PKIX errors, chain assembly, and JDK-version-specific paths are covered in a separate PKIX troubleshooting post. Here we only hit the essentials.

Cause ④ Corrupted local repository cache (~/.m2/repository)

If you can reach the repository fine but one specific library keeps failing and the log mentions .lastUpdated, a download was interrupted and the cache is corrupted. Maven leaves a failure marker (*.lastUpdated) and won't retry for a while.

Before wiping all of .m2, clear just the failure markers—it's much faster.

Bash
# 1) 실패 마커만 삭제 (가장 가볍고 안전)
find ~/.m2 -name "*.lastUpdated" -delete

# 2) 특정 의존성만 정리 후 재다운로드
mvn dependency:purge-local-repository -Dinclude=org.springframework:spring-core

# 3) 그래도 안 되면 강제 업데이트로 재시도
mvn -U clean install

A full rm -rf ~/.m2/repository is a last resort. You'll re-download several GB, which is especially wasteful in CI.

Cause ⑤ Version conflict, nonexistent version, or undeployed SNAPSHOT

If you clearly see a 404 like Could not find artifact ...:jar:1.2.3 in central (404), this is not a connectivity problem. You reached the repository; that coordinate (groupId:artifactId:version) simply doesn't exist. The three usual causes:

  • A typo or a version that doesn't exist (e.g. a nonexistent 1.2.3)
  • A colleague ran mvn install locally but never deployed the SNAPSHOT to Nexus
  • A version conflict from a transitive dependency pulled in by another library
Bash
# 어떤 라이브러리가 문제의 버전을 끌고 오는지 정확히 추적
mvn dependency:tree -Dverbose -Dincludes=com.example:problem-lib

Distinguishing Connection refused (②) from 404 (⑤) is the key. The former means "couldn't open the door"; the latter means "the door opened, but the item isn't there."

Cause ⑥ Misused -U / -o flags

Finally, flags trip people up more often than you'd think.

  • -o (offline): Offline mode. Maven can't fetch new dependencies; if they aren't in the cache you get Cannot access ... in offline mode. Don't leave it on out of habit.
  • -U (update): Forces SNAPSHOTs to be re-fetched. Useful in CI when you need the latest SNAPSHOT, but turning it on for every build adds unnecessary network calls and intermittent failures.
Bash
# SNAPSHOT 최신본이 필요할 때만
mvn -U clean install

5-minute diagnostic flowchart

Walk the error text down this list in order and you'll land on your case.

  1. Does the log contain PKIX or valid certification path? → Yes: cause ③ (import the certificate)
  2. Is there a 404 or Could not find artifact? → Yes: cause ⑤ (check version / SNAPSHOT)
  3. Connection refused / timed out and the failing URL is internal Nexus? → Yes: cause ① (check mirror and auth)
  4. Connection timed out and the URL is Maven Central? → Yes: cause ② (configure the proxy)
  5. Is .lastUpdated mentioned, or do only one or two artifacts fail? → Yes: cause ④ (find ~/.m2 -name "*.lastUpdated" -delete)
  6. Is there an offline mode message? → Yes: cause ⑥ (remove -o)

If these six steps don't catch it, temporarily disable settings.xml and run once in a vanilla environment to isolate environment variables.

What I've learned in practice

In my experience, 80% of "new hire's laptop won't build" failures on air-gapped projects were causes ① and ③. Once teams started shipping a known-good settings.xml plus the internal CA cert via an onboarding script, the "the build doesn't work" tickets almost disappeared. Version-controlling a standard settings.xml is far cheaper than having every individual debug it.

Recurrence-prevention checklist

  • Version-control a team-standard settings.xml; keep passwords in environment variables
  • Cache ~/.m2/repository in CI (GitHub Actions/Jenkins), but exclude *.lastUpdated from the cache key
  • Use -U only on jobs that must refresh SNAPSHOTs; leave it off for regular builds
  • Standardize every repository URL on https:// (Maven Central no longer allows HTTP)
  • Bake the internal CA certificate into the JDK image / onboarding script

FAQ

Q. Are Could not resolve dependencies and Failed to execute goal different errors? A. They're effectively one package. Failed to execute goal is the outer message that a plugin stopped; Could not resolve dependencies is the direct cause. Always look one level down at the Caused by or Could not transfer artifact line for the real reason.

Q. Is it okay to delete all of ~/.m2/repository? A. Yes, but it's a last resort. First delete only the failure markers with find ~/.m2 -name "*.lastUpdated" -delete, or purge just the bad dependency with mvn dependency:purge-local-repository. A full wipe forces a multi-GB re-download and is especially inefficient in CI.

Q. How do I tell a 404 from Connection refused? A. A 404 means "reached the repository, but that version isn't there" (cause ⑤). Connection refused/timed out means "couldn't reach the repository at all" (causes ① and ②). For 404, check the version and whether the SNAPSHOT was deployed; for refused, check the mirror URL and proxy settings.

확인 정보
✦ ✦ ✦
편집 검토 · Editorial Review

Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

편집 책임 · Nodelog 기술 편집팀·발행 · ·업데이트 ·

Comments

Be the first to comment.