SonarSource/sonarqube · error · IllegalArgumentException
Cannot provide an Azure DevOps access token for project '%s'
Error message
Cannot provide an Azure DevOps access token for project '%s': invalid Azure DevOps configuration: %s
What it means
AzureDevOpsScmAccessTokenProvider.passThrough() validates the ALM binding before minting an SCM access token for a project. If AzureDevOpsValidator.validate() rejects the AlmSettingDto (bad URL, missing PAT, malformed configuration), it rethrows as IllegalArgumentException with the project key and underlying validation message embedded.
Source
Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/azuredevops/AzureDevOpsScmAccessTokenProvider.java:119
Optional<ProjectAlmSettingDto> projectAlmSetting = dbClient.projectAlmSettingDao().selectByProject(dbSession, project.get());
if (projectAlmSetting.isEmpty()) {
LOG.warn("Cannot provide an Azure DevOps access token: project '{}' is not bound to any DevOps Platform", safeProjectKey);
return Optional.empty();
}
return dbClient.almSettingDao().selectByUuid(dbSession, projectAlmSetting.get().getAlmSettingUuid())
.filter(almSetting -> almSetting.getAlm() == ALM.AZURE_DEVOPS);
}
private ScmAccessToken passThrough(String safeProjectKey, AlmSettingDto almSetting) {
// AzureDevOpsValidator.validate() can fail with either IllegalArgumentException (bad config) or
// NullPointerException (missing URL/PAT via requireNonNull) — caught here as RuntimeException,
// rather than naming NullPointerException explicitly, to avoid catching it as a control-flow signal.
try {
azureDevOpsValidator.validate(almSetting);
} catch (RuntimeException e) {
throw new IllegalArgumentException(
format("Cannot provide an Azure DevOps access token for project '%s': invalid Azure DevOps configuration: %s", safeProjectKey, e.getMessage()), e);
}
String personalAccessToken = requireNonNull(almSetting.getDecryptedPersonalAccessToken(encryption), "Azure DevOps personal access token cannot be null");
// Azure DevOps PATs are long-lived, admin-managed credentials with their own separate expiry — not
// minted per call — so there is no per-request expiry to report here.
return new ScmAccessToken(ALM.AZURE_DEVOPS.getId(), GIT_USERNAME, personalAccessToken, null);
}
/**
* Strips CR/LF from the user-controlled project key before logging it, so a crafted value cannot
* forge extra log lines/entries (CWE-117).
*/
private static String sanitizeForLog(String value) {
return CRLF_PATTERN.matcher(value).replaceAll("_");
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Fix the Azure DevOps ALM binding in Administration > DevOps Platform Integrations: set a valid URL and a PAT with Code Read scope
- Re-enter the PAT so it is re-encrypted with the current encryption key, then retry
- Call the API only after the binding validates, e.g. run the Azure DevOps integration's validation beforehand
- Check the embedded cause message in the error for the exact validation failure
Example fix
// before almSettingDto with personalAccessToken = null // after almSettingDto.setPersonalAccessToken(encryption.encrypt(pat)) // valid PAT with Code Read scope
Defensive patterns
Strategy: validation
Validate before calling
// pre-validate the ALM binding before requesting tokens
const alm = await getAlmSetting('azure');
if (!alm?.url || !/^https:\/\//.test(alm.url) || !alm.personalAccessTokenExists) {
throw new Error('Azure DevOps binding incomplete: set endpoint URL and PAT first');
} Type guard
null
Try / catch
try {
const token = scmAccessTokenProvider.getAccessToken(projectKey);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("invalid Azure DevOps configuration")) {
// fix alm_settings binding; cause holds the validation detail
} else throw e;
} Prevention
- Verify the DevOps Platform integration validates (URL + PAT) before projects reference it
- Re-enter PATs after encryption key changes
- Check alm_settings rows for null/blank fields after scripted setup
- Pin PAT scope to Code Read and track expiry
When it happens
Trigger: Requesting an Azure DevOps access token for a project whose alm_pats/alm_settings binding is misconfigured: null or blank personal access token, invalid endpoint URL, or any validator RuntimeException (including NPE from missing URL/PAT via requireNonNull).
Common situations: Administrator deleted or cleared the Azure DevOps PAT; alm_settings entry created via API with missing fields; encryption key changed so decrypted PAT comes back null.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Invalid Azure URL or Personal Access Token
- Invalid Azure URL
- Global personal access tokens ("All accessible organizations
- Your global Bitbucket Server configuration is incomplete.
- Missing URL
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/0e57cbf416229a19.
Report an issue: GitHub.