SonarSource/sonarqube · error · IllegalArgumentException
Unable to contact Bitbucket Cloud servers: Check your creden
Error message
Unable to contact Bitbucket Cloud servers: Check your credentials
What it means
During validateAccessToken() the OAuth token exchange at bitbucket.org/site/oauth2/access_token failed with error body field 'error' equal to 'unauthorized_client'; the client translates that into IllegalArgumentException('Unable to contact Bitbucket Cloud servers: Check your credentials'). Bitbucket emits unauthorized_client when the client credentials presented in the Basic Authorization header are rejected, i.e. the Key/Secret pair is wrong, revoked, or the consumer cannot use this grant.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java:140
throw new IllegalArgumentException(e.getMessage());
}
}
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);
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Re-copy the OAuth consumer's Key and Secret from Bitbucket Workspace Settings > OAuth consumers into SonarQube's Bitbucket Cloud configuration, trimming whitespace/newlines
- If the secret was rotated, generate/use the current secret (or reset it in Bitbucket) and save the configuration again
- Verify the consumer still exists and is enabled in the workspace whose slug you configured
- Retry 'Check configuration' in SonarQube after fixing the credentials
Example fix
// before clientId = "ASDFGHJK"; // wrong consumer key clientSecret = "oldRevokedSecret"; // rotated in Bitbucket client.validate(clientId, clientSecret, workspace); // after clientId = "currentConsumerKey".trim(); clientSecret = "currentConsumerSecret".trim(); client.validate(clientId, clientSecret, workspace);
Defensive patterns
Strategy: validation
Validate before calling
// Pre-verify credentials before saving them in configuration
// curl -s -X POST -u "$CLIENT_KEY":"$CLIENT_SECRET" -d grant_type=client_credentials \
// https://bitbucket.org/site/oauth2/access_token
// "unauthorized_client" => key/secret rejected: fix before persisting.
if (clientId == null || clientId.isBlank() || clientSecret == null || clientSecret.isBlank()) {
throw new IllegalArgumentException("Bitbucket OAuth client id and secret are required");
}
if (clientId.contains("\n") || clientSecret.contains("\n")) {
throw new IllegalArgumentException("OAuth credentials contain stray newlines; re-copy from Bitbucket");
} Try / catch
try {
client.validate(clientId, clientSecret, workspace);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Check your credentials")) {
log.error("Bitbucket OAuth Key/Secret rejected (unauthorized_client); re-copy from workspace OAuth consumers");
}
throw e;
} Prevention
- Store Key/Secret in a secret manager and copy programmatically to avoid trailing whitespace/newlines
- If the secret was rotated in Bitbucket, update SonarQube immediately — old secrets fail with unauthorized_client
- Verify you are using the Key (client id) and Secret (client secret) of the same consumer in the same workspace
- Never swap Key and Secret fields when configuring
When it happens
Trigger: Calling BitbucketCloudRestClient.validate(clientId, clientSecret, workspace): the POST with grant_type=client_credentials and Basic base64(clientId:clientSecret) gets a 40x response whose JSON body has "error":"unauthorized_client" — hit when the OAuth consumer's Key or Secret is mistyped/stale/rotated, or the consumer does not permit the client_credentials grant.
Common situations: Client secret rotated in Bitbucket but the old secret still stored in SonarQube; Key/Secret swapped or pasted with surrounding whitespace/newline; using the consumer Key of a different workspace; SonarQube settings updated to a consumer that was deleted.
Related errors
- Unable to contact Bitbucket Cloud servers: Configure the OAu
- Can not get Bitbucket user profile. HTTP code: %s, response:
- Error returned by Bitbucket Cloud: %s
- Unable to contact Bitbucket Cloud servers
- Authentication failed, verify the Client Id, Client Secret a
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/b603d772b19d460f.
Report an issue: GitHub.