{"record":{"id":"38b5df68537c2471","repo":"SonarSource/sonarqube","slug":"invalid-azure-url","errorCode":null,"errorMessage":"Invalid Azure URL","messagePattern":"Invalid Azure URL","errorType":"http","errorClass":"AzureDevopsServerException","httpStatus":404,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/azure/AzureDevOpsHttpClient.java","lineNumber":242,"sourceCode":"\n  protected static Request prepareRequestWithToken(String token, String method, HttpUrl url, @Nullable RequestBody body) {\n    return new Request.Builder()\n      .method(method, body)\n      .url(url)\n      .addHeader(\"Authorization\", encodeToken(\"accessToken:\" + token))\n      .build();\n  }\n\n  protected static void checkResponseIsSuccessful(Response response) throws IOException {\n    if (!response.isSuccessful()) {\n      if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {\n        LOG.error(\"{} for request [{}]: Invalid personal access token\", UNABLE_TO_CONTACT_AZURE_SERVER, response.request().url());\n        throw new AzureDevopsServerException(response.code(), \"Invalid personal access token\");\n      }\n\n      if (response.code() == HttpURLConnection.HTTP_NOT_FOUND) {\n        LOG.error(\"{} for request [{}]: URL Not Found\", UNABLE_TO_CONTACT_AZURE_SERVER, response.request().url());\n        throw new AzureDevopsServerException(response.code(), \"Invalid Azure URL\");\n      }\n\n      ResponseBody responseBody = response.body();\n      String body = responseBody.string();\n      String errorMessage = generateErrorMessage(body);\n      LOG.error(\"Azure API call to [{}] failed with {} http code. Azure response content : [{}]\", response.request().url(), response.code(), body);\n      throw new AzureDevopsServerException(response.code(), errorMessage);\n    }\n  }\n\n  protected static String generateErrorMessage(String body) {\n    GsonAzureError gsonAzureError = null;\n    try {\n      gsonAzureError = buildGson().fromJson(body, GsonAzureError.class);\n    } catch (JsonSyntaxException e) {\n      // not a json payload, ignore the error\n    }\n    if (gsonAzureError != null && !Strings.isNullOrEmpty(gsonAzureError.message())) {","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/azure/AzureDevOpsHttpClient.java#L224-L260","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["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).","Verify the project/repository still exists at the configured path on the Azure instance.","Check the URL in a browser / with curl to confirm it returns the expected resource, not 404.","Distinguish Server vs Services URL forms and use the matching one for your instance."],"exampleFix":"// before\nurl=https://devops.server.com (404, no collection)\n\n// after\nurl=https://devops.server.com/DefaultCollection","handlingStrategy":"validation","validationCode":"static boolean urlExists(String azureUrl, String pat) throws Exception {\n  HttpURLConnection c = (HttpURLConnection) new java.net.URI(azureUrl + \"/_apis/projects\").toURL().openConnection();\n  c.setRequestProperty(\"Authorization\", \"Basic \" + Base64.getEncoder().encodeToString((\":\" + pat).getBytes()));\n  return c.getResponseCode() != 404;\n}","typeGuard":null,"tryCatchPattern":"try {\n  client.importAzureRepos(url, pat);\n} catch (AzureDevopsServerException e) {\n  if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) {\n    throw new ConfigurationException(\"Azure URL not found — include the collection path (e.g. https://server/DefaultCollection)\", e);\n  }\n  throw e;\n}","preventionTips":["Verify the configured URL resolves in a browser/curl before saving the integration.","For Azure DevOps Server always include the collection name in the URL.","Re-check the URL after projects or collections are renamed or migrated on Azure.","Do not confuse Azure DevOps Services (dev.azure.com/org) and Server (https://server/collection) URL formats."],"tags":["java","azure-devops","http","configuration"],"backgroundTag":"resource-not-found","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}