SonarSource/sonarqube · error · AzureDevopsServerException
generateErrorMessage(body)
Error message
generateErrorMessage(body)
What it means
AzureDevOpsHttpClient.isGlobalPat treats non-successful responses that are not 401/403 as an Azure-side failure and throws AzureDevopsServerException carrying the HTTP code and an error message extracted from the response body (generateErrorMessage). It occurs while checking whether a personal access token is a global (all-organizations) PAT.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/azure/AzureDevOpsHttpClient.java:183
}
protected boolean isGlobalPat(String vsspsGlobalUrl, String token) {
HttpUrl url = Objects.requireNonNull(HttpUrl.parse(vsspsGlobalUrl), INVALID_SERVER_URL)
.newBuilder()
.addPathSegment(PATH_APIS)
.addPathSegment(PATH_CONNECTION_DATA)
.addQueryParameter(PARAM_API_VERSION, API_VERSION_3_PREVIEW_VALUE)
.build();
Request request = prepareRequestWithToken(token, GET, url, null);
try (Response response = globalPatProbeClient.newCall(request).execute()) {
if (response.code() == HttpURLConnection.HTTP_OK) {
return true;
}
if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED || response.code() == HttpURLConnection.HTTP_FORBIDDEN) {
return false;
}
String body = Objects.requireNonNull(response.body(), MISSING_RESPONSE_BODY).string();
throw new AzureDevopsServerException(response.code(), generateErrorMessage(body));
} catch (IOException e) {
throw new IllegalArgumentException(
String.format(UNABLE_TO_CONTACT_AZURE_SERVER_MESSAGE_FORMAT, UNABLE_TO_CONTACT_AZURE_SERVER, request.url(), e.getMessage()), e);
}
}
private void doGet(String token, HttpUrl url) {
Request request = prepareRequestWithToken(token, GET, url, null);
doCall(request);
}
protected void doCall(Request request) {
try (Response response = client.newCall(request).execute()) {
checkResponseIsSuccessful(response);
} catch (IOException e) {
throw new IllegalArgumentException(
String.format(UNABLE_TO_CONTACT_AZURE_SERVER_MESSAGE_FORMAT, UNABLE_TO_CONTACT_AZURE_SERVER, request.url(), e.getMessage()),
e);View on GitHub (pinned to 184c821202)
Solutions
- Read the AzureDevopsServerException code/message: fix the URL if 404, or wait and retry if 5xx.
- Verify the Azure DevOps Server base URL includes the collection path (e.g. https://server/tfs/DefaultCollection).
- Check Azure DevOps Server health / event log if the code is 500/503.
- If a proxy returns the error, bypass the proxy or trust it for SonarQube requests.
Example fix
// before URL=https://devops.server.com (missing collection) // after URL=https://devops.server.com/DefaultCollection
Defensive patterns
Strategy: try-catch
Validate before calling
// verify server URL exists before isGlobalPat-style checks
HttpResponse<String> resp = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() == 404) {
throw new IllegalArgumentException("Azure DevOps URL invalid: check collection path");
} Try / catch
try {
boolean global = client.isGlobalPat(pat);
} catch (AzureDevopsServerException e) {
switch (e.getCode()) {
case 404: throw new ConfigurationException("Invalid Azure URL/collection", e);
case 503: /* retry later */ break;
default: throw new ConfigurationException("Azure server error " + e.getCode(), e);
}
} Prevention
- Include the collection path in Azure DevOps Server URLs.
- Validate the server URL in a browser before configuring the integration.
- Monitor Azure DevOps Server health during maintenance windows.
- Check what the response body says — it is embedded in the exception message.
When it happens
Trigger: During isGlobalPat the Azure DevOps Server responds with a status other than 200 or 401/403 — e.g. 404 (wrong collection/URL), 408/503 (server overloaded), or 500 — and the response body is parsed into an error message.
Common situations: Typo in the Azure DevOps Server URL (missing collection name), Azure server under maintenance returning 503, proxy intercepting the request and returning a custom error page.
Related errors
- Invalid Azure URL
- Error while executing a call to %s. Return code %s. Error me
- SonarQube was not able to retrieve resources from external s
- %s for request [%s]: [%s]
- Response from Azure for request [%s] could not be parsed: [%
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/8d659c52501a0808.
Report an issue: GitHub.