SonarSource/sonarqube · error · IllegalStateException

Cannot obtain Azure Access Token. Details:

Error message

Cannot obtain Azure Access Token. Details: 

What it means

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.

Solutions

  1. Read the 'Details' suffix in the exception message for the exact Azure error (auth failure, throttling, etc.)
  2. Verify the Azure subscription is active and linked correctly in SonarCloud/Azure Marketplace
  3. Retry later if the details indicate throttling or a transient Azure error
  4. Check the configured Azure resource ID / environment matches your subscription
  5. Upgrade SonarQube if Azure changed its API contract

Example fix

// before
throw new IllegalStateException("Cannot obtain Azure Access Token. Details: " + response.message());
// after
if (response.code() == 429) {
  throw new IllegalStateException("Azure rate limit hit, retry later. Details: " + response.message());
}
throw new IllegalStateException("Cannot obtain Azure Access Token. Details: " + response.message());
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the Azure subscription is active/linked before billing; Azure itself will
// reject the token exchange otherwise.
// e.g. check subscription state via the Azure API: state === 'Active'

Type guard

null

Try / catch

try {
  await billAzureAccount(subscriptionId);
} catch (err) {
  const details = (err.message || '').split('Details:')[1];
  if (details && /401|403|Unauthorized/i.test(details)) {
    // fix Azure Marketplace subscription linkage/credentials
  } else if (details && /429|throttl/i.test(details)) {
    // retry later with backoff
  } else { throw err; }
}

Prevention

When it happens

Trigger: 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).

Common situations: Invalid or revoked Azure Marketplace subscription credentials, expired subscription, Azure throttling the request, Azure outage, wrong resource/tenant configuration.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/azurebilling/service/DefaultAzureBillingHandler.java:87

    String clientId = azureEnvironment.getAzureClientId()
      .orElseThrow(() -> new IllegalStateException("Azure Client ID is not configured"));

    Request tokenRequest = azureBillingRequestBuilder.getAzureUserTokenRequest(clientId);

    try (Response response = client.newCall(tokenRequest).execute()) {
      if (response.isSuccessful()) {
        Optional<String> accessToken = azureBillingResponseHandler.extractAccessTokenFromResponse(response);

        if (accessToken.isPresent()) {
          return accessToken.get();
        } else {
          logError("Cannot extract Azure Access Token from response.");
          throw new IllegalStateException("Cannot extract Azure Access Token from response");
        }
      } else {
        logError(response.message());
        throw new IllegalStateException("Cannot obtain Azure Access Token. Details: " + response.message());
      }
    } catch (IOException e) {
      logError(e.getMessage());
      throw new IllegalStateException("Cannot obtain Azure Access Token. Details: " + e.getMessage());
    }
  }

  private String getResourceId() {
    return azureEnvironment.getResourceId()
      .orElseThrow(() -> new IllegalStateException("Azure Resource ID is not configured"));
  }

  private String getPlanId() {
    return azureEnvironment.getPlanId()
      .orElseThrow(() -> new IllegalStateException("Azure Plan ID is not configured"));
  }

  @NotNull

View on GitHub (pinned to 184c821202)