SonarSource/sonarqube · error · IllegalArgumentException
Invalid Azure URL or Personal Access Token
Error message
Invalid Azure URL or Personal Access Token
What it means
AzureDevOpsValidator.validate wraps AzureDevOpsHttpClient.checkPAT: if the URL or PAT check fails with IllegalArgumentException (bad URL format, unreachable server, or invalid token), it rethrows with the generic message 'Invalid Azure URL or Personal Access Token', deliberately hiding the underlying cause from the user while keeping it as the cause for logs.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/azure/AzureDevOpsValidator.java:51
private static final Logger LOG = LoggerFactory.getLogger(AzureDevOpsValidator.class);
public static final String GLOBAL_PAT_ERROR_MESSAGE = "Global personal access tokens (\"All accessible organizations\") are being retired by " +
"Microsoft and cannot be used. Create a personal access token scoped to a single organization.";
private final AzureDevOpsHttpClient azureDevOpsHttpClient;
private final Settings settings;
public AzureDevOpsValidator(AzureDevOpsHttpClient azureDevOpsHttpClient, Settings settings) {
this.azureDevOpsHttpClient = azureDevOpsHttpClient;
this.settings = settings;
}
public void validate(AlmSettingDto dto) {
try {
azureDevOpsHttpClient.checkPAT(requireNonNull(dto.getUrl()),
requireNonNull(dto.getDecryptedPersonalAccessToken(settings.getEncryption())));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid Azure URL or Personal Access Token", e);
}
}
/**
* Denies binding an Azure DevOps Services (Cloud) organization with a Global PAT ("All accessible
* organizations"). Azure DevOps Server has no cross-org scope, so non-Cloud URLs are always allowed.
* A probe failure (network error, Microsoft outage) is treated as inconclusive and fails open, so a
* transient issue never blocks configuring a valid binding.
*/
public void checkPatIsNotGlobal(String url, String pat) {
if (!AzureDevOpsUrls.isAzureDevOpsServices(url)) {
return;
}
boolean isGlobal;
try {
isGlobal = azureDevOpsHttpClient.isGlobalPat(pat);
} catch (IllegalArgumentException e) {
LOG.warn("Unable to determine whether the Azure DevOps personal access token is global, allowing the binding", e);View on GitHub (pinned to 184c821202)
Solutions
- Check the server log for the wrapped IllegalArgumentException cause to see the exact failure.
- Verify the URL format: Azure DevOps Services https://dev.azure.com/{organization} or Server https://{server}/{collection}, reachable from the SonarQube host.
- Regenerate the PAT in Azure DevOps (User Settings > Personal Access Tokens) and paste it freshly, ensuring it hasn't expired.
- Test connectivity from the SonarQube server: curl to the Azure DevOps URL to rule out firewall/proxy issues.
Example fix
// before
almSetting.setUrl("dev.azure.com/myorg/");
// after
almSetting.setUrl("https://dev.azure.com/myorg"); Defensive patterns
Strategy: validation
Validate before calling
boolean validUrl = url != null && (url.startsWith("https://dev.azure.com/") || url.matches("https://.+/DefaultCollection"));
boolean validPat = pat != null && !pat.isBlank();
if (!validUrl || !validPat) throw new IllegalArgumentException("Provide a valid Azure DevOps URL and a non-expired PAT"); Try / catch
try {
validator.validate(dto);
} catch (IllegalArgumentException e) {
LOG.warn("Azure DevOps binding rejected", e); // cause holds the real reason
throw new UserFacingException("Check the Azure DevOps URL and Personal Access Token");
} Prevention
- Always include https:// and the organization/collection path in the URL.
- Set PAT expiry reminders; prefer long-expiry PATs for server integrations.
- Verify network egress from the SonarQube server to Azure DevOps.
- Check server logs for the wrapped cause when the generic message appears.
When it happens
Trigger: Calling validate(AlmSettingDto) when dto.getUrl() is malformed or not an Azure DevOps URL, the PAT is empty/expired/invalid, or checkPAT cannot contact the Azure DevOps instance (any IllegalArgumentException from the HTTP client).
Common situations: Admin saving an Azure DevOps ALM setting in SonarQube with a typo'd URL (missing https://dev.azure.com/org), a revoked or expired PAT, or a network/proxy blocking the SonarQube server from reaching Azure DevOps.
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
- Global personal access tokens ("All accessible organizations
- Cannot provide an Azure DevOps access token for project '%s'
- Invalid personal access token
- Invalid Azure URL
- Your global Bitbucket Server configuration is incomplete.
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/6219eac2600b297a.
Report an issue: GitHub.