Maven 401 Unauthorized from Repository - Fix Auth in CI
A private repository rejected Maven with a 401. Maven either sent no credentials or the wrong ones - the <server> entry in settings.xml does not match the repository <id>, or the token has expired.
What this error means
Resolution or deployment to a private repo fails with status code: 401, ReasonPhrase: Unauthorized. Public Central artifacts resolve fine; only the authenticated repo fails.
[ERROR] Failed to execute goal ... Could not transfer artifact
com.example:lib:jar:2.3.1 from/to company-releases
(https://nexus.example.com/...): status code: 401, ReasonPhrase: UnauthorizedCommon causes
No matching <server> credentials
Maven matches a repository to credentials by <id>. If the repository <id> in the POM does not exactly match a <server><id> in settings.xml, Maven sends no auth and gets 401.
Expired or wrong token in CI
The CI secret holding the repository token may be stale, scoped wrong, or not injected into settings.xml at all, so the request is unauthenticated.
How to fix it
Add a matching server entry
The <server><id> must equal the repository <id>. Inject username/token from CI secrets.
<settings>
<servers>
<server>
<id>company-releases</id>
<username>${env.MVN_REPO_USER}</username>
<password>${env.MVN_REPO_TOKEN}</password>
</server>
</servers>
</settings>Point Maven at the CI settings file
Generate settings.xml from secrets in the job, then pass it explicitly.
mvn -s ./.ci/settings.xml -B verifyHow to prevent it
- Keep repository
<id>and<server><id>identical across POM and settings.xml. - Inject repository tokens from CI secrets at build time, never commit them.
- Rotate and scope repository tokens to read-only where deployment is not needed.