Maven "401 Unauthorized" on Deploy - Fix Publishing Auth in CI
mvn deploy uploaded to a repository that refused the request with 401. The credentials in settings.xml are missing, wrong, or not bound to the distributionManagement repository id -- so no valid auth was sent for the publish.
What this error means
The deploy phase fails with Failed to deploy artifacts: Could not transfer artifact ... status code: 401 Unauthorized against the release/snapshot repo. Compilation and tests pass; only the upload is rejected, and it fails every run until auth is fixed.
[ERROR] Failed to execute goal ...:deploy (default-deploy) on project app:
Failed to deploy artifacts: Could not transfer artifact com.example:app:jar:1.4.0
from/to releases (https://nexus.example.com/releases): status code: 401 UnauthorizedCommon causes
distributionManagement id does not match a <server> id
Maven binds deploy credentials by id. If the <distributionManagement><repository><id> is not exactly equal to a <server><id> in settings.xml, no auth is sent and the repo answers 401.
Deploy token missing or wrong
The CI secret feeding the server password is empty, expired, or lacks publish scope, so the upload is unauthorized.
How to fix it
Write a settings.xml with matching ids from CI secrets
Generate the file in the job, with the server id equal to the distributionManagement id, and pass it explicitly.
cat > ./.ci/settings.xml <<'XML'
<settings>
<servers>
<server>
<id>releases</id>
<username>${env.MVN_DEPLOY_USER}</username>
<password>${env.MVN_DEPLOY_TOKEN}</password>
</server>
</servers>
</settings>
XML
mvn -B -s ./.ci/settings.xml deployVerify id match and token scope
- Confirm the distributionManagement repository
<id>equals the<server><id>, character for character. - Use a token with deploy/publish scope -- a read-only token authenticates but cannot upload.
- Run
mvn -X deployto see which server entry Maven selected for the deploy host.
How to prevent it
- Keep distributionManagement and server ids identical.
- Inject a publish-scoped deploy token from CI secrets at build time.
- Separate read tokens from deploy tokens so scope problems are obvious.