SonarSource/sonarqube · error · IllegalArgumentException
Error returned by Bitbucket Cloud: %s
Error message
Error returned by Bitbucket Cloud: %s
What it means
In validateAccessToken(), the token endpoint returned a non-success HTTP status whose body contained an 'error' string that is neither 'invalid_grant' nor 'unauthorized_client', but a JSON 'error_description' (parsedErrorMsg) was present. The client then throws IllegalArgumentException('Error returned by Bitbucket Cloud: ' + parsedErrorMsg), surfacing Bitbucket's own error description verbatim to the SonarQube admin. It is a pass-through wrapper around whatever OAuth error Bitbucket chose to report.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java:143
private Token validateAccessToken(String clientId, String clientSecret) {
Request request = createAccessTokenRequest(clientId, clientSecret);
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return buildGson().fromJson(response.body().charStream(), Token.class);
}
ErrorDetails errorMsg = getTokenError(response.body(), response.message());
if (errorMsg.body != null) {
LOG.atInfo().log(() -> String.format(BBC_FAIL_WITH_RESPONSE, response.request().url(), response.code(), errorMsg.body));
switch (errorMsg.body) {
case "invalid_grant":
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS + ": " + OAUTH_CONSUMER_NOT_PRIVATE);
case "unauthorized_client":
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS + ": " + UNAUTHORIZED_CLIENT);
default:
if (errorMsg.parsedErrorMsg != null) {
throw new IllegalArgumentException(ERROR_BBC_SERVERS + ": " + errorMsg.parsedErrorMsg);
} else {
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS);
}
}
} else {
LOG.atInfo().log(() -> String.format(BBC_FAIL_WITH_RESPONSE, response.request().url(), response.code(), response.message()));
}
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS);
} catch (IOException e) {
LOG.info(String.format(BBC_FAIL_WITH_ERROR, request.url(), e.getMessage()));
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS, e);
}
}
public RepositoryList searchRepos(String encodedApiTokenCredentials, String workspace, @Nullable String repoName, Integer page, Integer pageSize) {
String filterQuery = String.format("q=name~\"%s\"", repoName != null ? repoName : "");
HttpUrl url = buildUrl(String.format("/repositories/%s?%s&page=%s&pagelen=%s", workspace, filterQuery, page, pageSize));View on GitHub (pinned to 184c821202)
Solutions
- Read the 'Error returned by Bitbucket Cloud: <description>' suffix — it is Bitbucket's own error_description; address the OAuth issue it names
- Confirm the token request is exactly grant_type=client_credentials with the consumer's Key/Secret as HTTP Basic (no extra or missing parameters)
- Check the Bitbucket consumer is a private consumer in the correct workspace with Account/Repository/PullRequest read scopes
- Check Bitbucket Cloud status for ongoing incidents and retry if the description suggests a transient/server-side condition
- Inspect the server INFO log line 'Bitbucket Cloud API call to [...] failed with <code> http code' for the exact HTTP status
Example fix
// before: body {"error":"invalid_request","error_description":"grant_type not supported"}
// (thrown from validateAccessToken default branch)
// after: send the exact expected form
RequestBody body = new FormBody.Builder().add("grant_type", "client_credentials").build();
Request req = new Request.Builder().url(tokenUrl).header("Authorization", Credentials.basic(clientId, clientSecret)).post(body).build(); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight the exact token request and inspect the OAuth error_description
// curl -s -X POST -u "$KEY":"$SECRET" -d grant_type=client_credentials \
// https://bitbucket.org/site/oauth2/access_token
// The JSON 'error_description' field is what will appear after 'Error returned by Bitbucket Cloud: '
if (tokenResponse.contains("\"error_description\"")) {
String desc = extractJsonField(tokenResponse, "error_description");
throw new ConfigurationException("Bitbucket rejected the grant: " + desc);
} Try / catch
try {
client.validate(clientId, clientSecret, workspace);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Error returned by Bitbucket Cloud:")) {
// Bitbucket's own error_description follows — surface it verbatim to the admin
log.error("Bitbucket OAuth error: {}", e.getMessage());
}
throw e;
} Prevention
- Read the message suffix — it is Bitbucket's error_description and names the exact OAuth problem
- Keep the token request minimal: only grant_type=client_credentials; extra/missing params trigger invalid_request
- Verify no reverse proxy is intercepting bitbucket.org from the SonarQube server
- Check Bitbucket Cloud status for transient upstream errors before changing configuration
When it happens
Trigger: POST to https://bitbucket.org/site/oauth2/access_token with grant_type=client_credentials and Basic credentials returns a non-2xx response whose JSON body parses to TokenError with a non-null errorDescription and an 'error' value outside {invalid_grant, unauthorized_client} — e.g. 'invalid_request' (missing/malformed parameters), 'invalid_client' variants, or other OAuth errors with descriptions.
Common situations: Proxies or gateways rewriting the token request causing invalid_request; consumer misconfigured so Bitbucket rejects the grant with a descriptive message; temporarily returned upstream descriptions during Bitbucket incidents; custom reverse-proxy in front of bitbucket.org altering the request flow.
Related errors
- Unable to contact Bitbucket Cloud servers
- Unable to contact Bitbucket Cloud servers: Configure the OAu
- Unable to contact Bitbucket Cloud servers: Check your creden
- Can not get Bitbucket user profile. HTTP code: %s, response:
- User %s is not part of allowed workspaces list
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/638058496cbabdd1.
Report an issue: GitHub.