{"record":{"id":"9d84296e5eee61a5","repo":"SonarSource/sonarqube","slug":"cannot-extract-azure-access-token-from-response","errorCode":null,"errorMessage":"Cannot extract Azure Access Token from response","messagePattern":"Cannot extract Azure Access Token from response","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":83,"sourceCode":"    return handleAzureBillingRequest(request);\n  }\n\n  private String getAzureUserToken() {\n\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()","sourceCodeStart":65,"sourceCodeEnd":101,"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#L65-L101","documentation":"Thrown when the Azure Marketplace token-exchange endpoint responded successfully but its response body contained no parseable access token. DefaultAzureBillingHandler.getAzureUserToken treats this as an unexpected upstream response and raises IllegalStateException, which surfaces as a 500.","triggerScenarios":"billAzureAccount flow: the Azure billing API returns HTTP 2xx but azureBillingResponseHandler.extractAccessTokenFromResponse returns empty (changed response schema, empty body, missing token field).","commonSituations":"Azure changing the Marketplace billing API response format, a proxy returning an unexpected 200 HTML page, intermittent Azure-side issues producing empty token payloads.","solutions":["Retry the billing operation; Azure may return a well-formed response on a second attempt","Inspect the actual response body returned by Azure for the token endpoint","Verify Azure Marketplace billing API configuration (resource ID, endpoint) is current for your SonarQube version","Upgrade SonarQube to get updated Azure response parsing","Check network proxies are not altering the response"],"exampleFix":"// before\nif (accessToken.isPresent()) {\n  return accessToken.get();\n} else {\n  throw new IllegalStateException(\"Cannot extract Azure Access Token from response\");\n}\n// after\nif (accessToken.isPresent()) {\n  return accessToken.get();\n} else {\n  logError(\"Token exchange response body: \" + response.body());\n  throw new IllegalStateException(\"Cannot extract Azure Access Token from response. Raw body: \" + response.body());\n}","handlingStrategy":"retry","validationCode":"// No client-side pre-check can detect a malformed Azure response; verify connectivity\n// and that the instance is properly linked to an active Azure Marketplace subscription\n// before triggering billing:\n// GET /api/v2/azure/billing (or subscription status) must succeed first.","typeGuard":"null","tryCatchPattern":"try {\n  await billAzureAccount(subscriptionId);\n} catch (err) {\n  if (err.status >= 500 && /Cannot extract Azure Access Token/.test(err.message || '')) {\n    // retry with backoff; if persistent, report to SonarSource with the response body\n  } else { throw err; }\n}","preventionTips":["Retry transient billing failures with exponential backoff","Keep SonarQube/SonarCloud updated for current Azure response parsing","Log full upstream response bodies for diagnosing schema changes","Confirm the Azure subscription is active and linked before billing"],"tags":["sonarqube","azure","oauth","token-exchange"],"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"}