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

  1. Read the AzureDevopsServerException code/message: fix the URL if 404, or wait and retry if 5xx.
  2. Verify the Azure DevOps Server base URL includes the collection path (e.g. https://server/tfs/DefaultCollection).
  3. Check Azure DevOps Server health / event log if the code is 500/503.
  4. 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

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


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/8d659c52501a0808. Report an issue: GitHub.