{"record":{"id":"723305073adfde6e","repo":"SonarSource/sonarqube","slug":"cannot-obtain-azure-access-token-details","errorCode":null,"errorMessage":"Cannot obtain Azure Access Token. Details: ","messagePattern":"Cannot obtain Azure Access Token\\. Details: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":500,"severity":"error","filePath":"server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/azurebilling/service/DefaultAzureBillingHandler.java","lineNumber":87,"sourceCode":"\n    String clientId = azureEnvironment.getAzureClientId()\n      .orElseThrow(() -> new IllegalStateException(\"Azure Client ID is not configured\"));\n\n    Request tokenRequest = azureBillingRequestBuilder.getAzureUserTokenRequest(clientId);\n\n    try (Response response = client.newCall(tokenRequest).execute()) {\n      if (response.isSuccessful()) {\n        Optional<String> accessToken = azureBillingResponseHandler.extractAccessTokenFromResponse(response);\n\n        if (accessToken.isPresent()) {\n          return accessToken.get();\n        } else {\n          logError(\"Cannot extract Azure Access Token from response.\");\n          throw new IllegalStateException(\"Cannot extract Azure Access Token from response\");\n        }\n      } else {\n        logError(response.message());\n        throw new IllegalStateException(\"Cannot obtain Azure Access Token. Details: \" + response.message());\n      }\n    } catch (IOException e) {\n      logError(e.getMessage());\n      throw new IllegalStateException(\"Cannot obtain Azure Access Token. Details: \" + e.getMessage());\n    }\n  }\n\n  private String getResourceId() {\n    return azureEnvironment.getResourceId()\n      .orElseThrow(() -> new IllegalStateException(\"Azure Resource ID is not configured\"));\n  }\n\n  private String getPlanId() {\n    return azureEnvironment.getPlanId()\n      .orElseThrow(() -> new IllegalStateException(\"Azure Plan ID is not configured\"));\n  }\n\n  @NotNull","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/azurebilling/service/DefaultAzureBillingHandler.java#L69-L105","documentation":"Thrown when the Azure token exchange HTTP call completes but returns a non-success status; the handler raises IllegalStateException embedding Azure's error message, which surfaces as a 500 from the billing endpoint.","triggerScenarios":"billAzureAccount flow: azureBillingCaller returns a response whose status is not the expected success code (e.g. 401/403/429/5xx from the Azure billing endpoint).","commonSituations":"Invalid or revoked Azure Marketplace subscription credentials, expired subscription, Azure throttling the request, Azure outage, wrong resource/tenant configuration.","solutions":["Read the 'Details' suffix in the exception message for the exact Azure error (auth failure, throttling, etc.)","Verify the Azure subscription is active and linked correctly in SonarCloud/Azure Marketplace","Retry later if the details indicate throttling or a transient Azure error","Check the configured Azure resource ID / environment matches your subscription","Upgrade SonarQube if Azure changed its API contract"],"exampleFix":"// before\nthrow new IllegalStateException(\"Cannot obtain Azure Access Token. Details: \" + response.message());\n// after\nif (response.code() == 429) {\n  throw new IllegalStateException(\"Azure rate limit hit, retry later. Details: \" + response.message());\n}\nthrow new IllegalStateException(\"Cannot obtain Azure Access Token. Details: \" + response.message());","handlingStrategy":"try-catch","validationCode":"// Verify the Azure subscription is active/linked before billing; Azure itself will\n// reject the token exchange otherwise.\n// e.g. check subscription state via the Azure API: state === 'Active'","typeGuard":"null","tryCatchPattern":"try {\n  await billAzureAccount(subscriptionId);\n} catch (err) {\n  const details = (err.message || '').split('Details:')[1];\n  if (details && /401|403|Unauthorized/i.test(details)) {\n    // fix Azure Marketplace subscription linkage/credentials\n  } else if (details && /429|throttl/i.test(details)) {\n    // retry later with backoff\n  } else { throw err; }\n}","preventionTips":["Read the Details suffix to identify the exact Azure rejection reason","Keep the Azure Marketplace subscription active and correctly linked","Back off and retry on throttling responses","Monitor Azure status pages for ongoing incidents"],"tags":["sonarqube","azure","oauth","http-error"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}