{"record":{"id":"585e9c4139683e66","repo":"SonarSource/sonarqube","slug":"unable-to-contact-bitbucket-cloud-servers","errorCode":null,"errorMessage":"Unable to contact Bitbucket Cloud servers","messagePattern":"Unable to contact Bitbucket Cloud servers","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java","lineNumber":145,"sourceCode":"    Request request = createAccessTokenRequest(clientId, clientSecret);\n    try (Response response = client.newCall(request).execute()) {\n      if (response.isSuccessful()) {\n        return buildGson().fromJson(response.body().charStream(), Token.class);\n      }\n\n      ErrorDetails errorMsg = getTokenError(response.body(), response.message());\n      if (errorMsg.body != null) {\n        LOG.atInfo().log(() -> String.format(BBC_FAIL_WITH_RESPONSE, response.request().url(), response.code(), errorMsg.body));\n        switch (errorMsg.body) {\n          case \"invalid_grant\":\n            throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS + \": \" + OAUTH_CONSUMER_NOT_PRIVATE);\n          case \"unauthorized_client\":\n            throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS + \": \" + UNAUTHORIZED_CLIENT);\n          default:\n            if (errorMsg.parsedErrorMsg != null) {\n              throw new IllegalArgumentException(ERROR_BBC_SERVERS + \": \" + errorMsg.parsedErrorMsg);\n            } else {\n              throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS);\n            }\n        }\n      } else {\n        LOG.atInfo().log(() -> String.format(BBC_FAIL_WITH_RESPONSE, response.request().url(), response.code(), response.message()));\n      }\n      throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS);\n\n    } catch (IOException e) {\n      LOG.info(String.format(BBC_FAIL_WITH_ERROR, request.url(), e.getMessage()));\n      throw new IllegalArgumentException(UNABLE_TO_CONTACT_BBC_SERVERS, e);\n    }\n  }\n\n  public RepositoryList searchRepos(String encodedApiTokenCredentials, String workspace, @Nullable String repoName, Integer page, Integer pageSize) {\n    String filterQuery = String.format(\"q=name~\\\"%s\\\"\", repoName != null ? repoName : \"\");\n    HttpUrl url = buildUrl(String.format(\"/repositories/%s?%s&page=%s&pagelen=%s\", workspace, filterQuery, page, pageSize));\n    return doGetWithApiToken(encodedApiTokenCredentials, url, r -> buildGson().fromJson(r.body().charStream(), RepositoryList.class));\n  }","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java#L127-L163","documentation":"validateAccessToken() reached a state where it could not produce a specific OAuth error message: either the token endpoint returned a non-success status with a body whose 'error' string was unrecognized and had no parseable error_description, or the response had no usable error body at all. In both cases the client throws IllegalArgumentException('Unable to contact Bitbucket Cloud servers'). It is the generic fallback for any token-exchange failure against Bitbucket Cloud that lacks a diagnosable body, including pure transport IOExceptions.","triggerScenarios":"Calling BitbucketCloudRestClient.validate(clientId, clientSecret, workspace) where: (1) the access_token POST returns non-2xx with a body having no parseable error/error_description (HTML error page, blank body, empty response) — line 145 and the trailing line-151 throw after the else branch logs; (2) an IOException occurs during the call (DNS failure, connection reset, TLS error, timeout) — line 155 throw of the same message; (3) response body is not JSON so getTokenError falls back to the raw body string with no parsedErrorMsg.","commonSituations":"SonarQube server cannot reach bitbucket.org (firewall/proxy/DNS misconfiguration, proxy auth required); corporate TLS interception breaking the handshake; Bitbucket returning an HTML 502/503 error page during incidents; OIDC/proxy stripping the response body; timeouts under load.","solutions":["Test connectivity from the SonarQube server: curl -v https://bitbucket.org/site/oauth2/access_token; fix DNS/firewall/proxy settings (sonar.properties proxy options) accordingly","Check the server INFO logs for the preceding 'Bitbucket Cloud API call to [...] failed with error: <IOException message>' or 'failed with <code> http code' lines to identify the transport cause","If a corporate proxy/TLS appliance is present, install its CA into the JVM truststore or bypass it for *.bitbucket.org","Check the Bitbucket Cloud status page for outages and retry the validation after incidents resolve","Confirm the configured clientId/secret are non-empty and the consumer is private so the more specific branches (invalid_grant/unauthorized_client) are reachable if applicable"],"exampleFix":"// before (proxy blocks egress, IOException -> 'Unable to contact Bitbucket Cloud servers')\n# sonar.properties (no proxy)\n// after\nsonar.proxy.host=proxy.corp.example.com\nsonar.proxy.port=8080\nsonar.proxy.user=svc-sonar\nsonar.proxy.password=<proxy-password>","handlingStrategy":"retry","validationCode":"// Pre-check reachability of the token endpoint before configuring\nProcessResult r = exec(\"curl -s -o /dev/null -w %{http_code} --max-time 10 https://bitbucket.org/site/oauth2/access_token\");\nif (!\"000\".equals(r.output()) && Integer.parseInt(r.output()) >= 500) {\n  throw new EnvironmentException(\"bitbucket.org unreachable/unhealthy from this host; fix network before configuring\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  client.validate(clientId, clientSecret, workspace);\n} catch (IllegalArgumentException e) {\n  if (\"Unable to contact Bitbucket Cloud servers\".equals(e.getMessage())) {\n    // generic transport/unparsed failure: retry with backoff, then check connectivity\n    retryWithBackoff(() -> client.validate(clientId, clientSecret, workspace), 3);\n  }\n  throw e;\n}","preventionTips":["Ensure the SonarQube host can reach bitbucket.org and api.bitbucket.org (DNS, firewall, proxy config in sonar.properties)","For corporate TLS inspection, add the proxy CA to the JVM truststore (cacerts)","Watch the INFO logs — the IOException or HTTP code logged just before this message pinpoints the transport cause","Check the Bitbucket Cloud status page during incidents rather than troubleshooting credentials","Retry validation after transient network faults; this message is the expected symptom of pure connectivity loss"],"tags":["bitbucket","oauth","network","http-client"],"backgroundTag":"network-request-failed","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}