SonarSource/sonarqube · error · AzureDevopsServerException

Invalid Azure URL

Error message

Invalid Azure URL

What it means

checkResponseIsSuccessful maps HTTP 404 from Azure DevOps to AzureDevopsServerException(code=404, 'Invalid Azure URL'). The request URL does not exist on the server, meaning the configured Azure DevOps URL (or project/repository path) is wrong for this instance.

Source

Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/azure/AzureDevOpsHttpClient.java:242

  protected static Request prepareRequestWithToken(String token, String method, HttpUrl url, @Nullable RequestBody body) {
    return new Request.Builder()
      .method(method, body)
      .url(url)
      .addHeader("Authorization", encodeToken("accessToken:" + token))
      .build();
  }

  protected static void checkResponseIsSuccessful(Response response) throws IOException {
    if (!response.isSuccessful()) {
      if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
        LOG.error("{} for request [{}]: Invalid personal access token", UNABLE_TO_CONTACT_AZURE_SERVER, response.request().url());
        throw new AzureDevopsServerException(response.code(), "Invalid personal access token");
      }

      if (response.code() == HttpURLConnection.HTTP_NOT_FOUND) {
        LOG.error("{} for request [{}]: URL Not Found", UNABLE_TO_CONTACT_AZURE_SERVER, response.request().url());
        throw new AzureDevopsServerException(response.code(), "Invalid Azure URL");
      }

      ResponseBody responseBody = response.body();
      String body = responseBody.string();
      String errorMessage = generateErrorMessage(body);
      LOG.error("Azure API call to [{}] failed with {} http code. Azure response content : [{}]", response.request().url(), response.code(), body);
      throw new AzureDevopsServerException(response.code(), errorMessage);
    }
  }

  protected static String generateErrorMessage(String body) {
    GsonAzureError gsonAzureError = null;
    try {
      gsonAzureError = buildGson().fromJson(body, GsonAzureError.class);
    } catch (JsonSyntaxException e) {
      // not a json payload, ignore the error
    }
    if (gsonAzureError != null && !Strings.isNullOrEmpty(gsonAzureError.message())) {

View on GitHub (pinned to 184c821202)

Solutions

  1. Correct the Azure DevOps URL in SonarQube settings to a URL that exists (for Azure DevOps Server include the collection, e.g. https://server/DefaultCollection).
  2. Verify the project/repository still exists at the configured path on the Azure instance.
  3. Check the URL in a browser / with curl to confirm it returns the expected resource, not 404.
  4. Distinguish Server vs Services URL forms and use the matching one for your instance.

Example fix

// before
url=https://devops.server.com (404, no collection)

// after
url=https://devops.server.com/DefaultCollection
Defensive patterns

Strategy: validation

Validate before calling

static boolean urlExists(String azureUrl, String pat) throws Exception {
  HttpURLConnection c = (HttpURLConnection) new java.net.URI(azureUrl + "/_apis/projects").toURL().openConnection();
  c.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString((":" + pat).getBytes()));
  return c.getResponseCode() != 404;
}

Try / catch

try {
  client.importAzureRepos(url, pat);
} catch (AzureDevopsServerException e) {
  if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) {
    throw new ConfigurationException("Azure URL not found — include the collection path (e.g. https://server/DefaultCollection)", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: doGet/doCall gets a 404 Not Found response: base URL missing the collection name, wrong host, project or repository deleted/renamed, or API version path not present on that server version.

Common situations: Entering the web portal URL instead of the server/collection URL for Azure DevOps Server; migrating or renaming a project on Azure; pointing SonarQube at Azure DevOps Services URL while using a Server instance (or vice versa).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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