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

  1. Re-copy the OAuth consumer's Key and Secret from Bitbucket Workspace Settings > OAuth consumers into SonarQube's Bitbucket Cloud configuration, trimming whitespace/newlines
  2. If the secret was rotated, generate/use the current secret (or reset it in Bitbucket) and save the configuration again
  3. Verify the consumer still exists and is enabled in the workspace whose slug you configured
  4. 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

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


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