SonarSource/sonarqube · error · IllegalStateException
Error returned by Bitbucket Cloud
Error message
Error returned by Bitbucket Cloud
What it means
doCall executes the HTTP request and, when the call itself throws an IOException (no HTTP response at all: DNS failure, timeout, connection reset, TLS error), logs and rethrows it as IllegalStateException("Error returned by Bitbucket Cloud", e). Despite the wording, this is not an error returned by Bitbucket — it means the request never completed and no server response was received. Successful responses with non-2xx codes are instead routed to handleError (error 24).
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java:233
protected <G> G doGetWithApiToken(String encodedApiTokenCredentials, HttpUrl url, Function<Response, G> handler) {
// Bitbucket Cloud expects API tokens to be transported as Basic authorization with base64(email:apiToken).
Request request = prepareRequestWithAuthorizationHeader("Basic " + encodedApiTokenCredentials, GET, url, null);
try {
return doCall(request, handler);
} catch (BitbucketCloudException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
protected <G> G doCall(Request request, Function<Response, G> handler) {
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
handleError(response);
}
return handler.apply(response);
} catch (IOException e) {
LOG.info(ERROR_BBC_SERVERS + ": {}", e.getMessage());
throw new IllegalStateException(ERROR_BBC_SERVERS, e);
}
}
private static void handleError(Response response) throws IOException {
ErrorDetails error = getError(response.body(), response.message());
int statusCode = response.code();
LOG.atInfo().log(() -> String.format(BBC_FAIL_WITH_RESPONSE, response.request().url(), statusCode, error.body));
String errorMessage;
if (error.parsedErrorMsg != null) {
errorMessage = ERROR_BBC_SERVERS + ": " + error.parsedErrorMsg + " [HTTP " + statusCode + "]";
} else {
errorMessage = UNABLE_TO_CONTACT_BBC_SERVERS + " [HTTP " + statusCode + "]";
}
throw new BitbucketCloudException(errorMessage, statusCode);
}
private static ErrorDetails getError(@Nullable ResponseBody body, @Nullable String fallbackMessage) throws IOException {
return getErrorDetails(body, fallbackMessage, s -> {View on GitHub (pinned to 184c821202)
Solutions
- Look at the IllegalStateException's cause (IOException) or the INFO log 'Error returned by Bitbucket Cloud: <message>' to identify the exact transport failure.
- Test connectivity from the SonarQube host: curl -v https://api.bitbucket.org/2.0/repositories/<workspace>.
- Configure JVM proxy settings (-Dhttps.proxyHost/-Dhttps.proxyPort/-Dhttps.nonProxyHosts) if a proxy is mandatory in your environment, then restart.
- If the failure is TLS-related, add the corporate CA certificate to the JVM truststore (cacerts).
- If it is a read timeout on large paginated responses, increase the OkHttp timeouts of the bitBucketCloudHttpClient bean and/or reduce page sizes.
Example fix
// before: no proxy configured, execute() throws IOException
Request r = new Request.Builder().url("https://api.bitbucket.org/2.0/repositories/ws").build();
// after: build the injected OkHttpClient with a proxy so execute() succeeds
OkHttpClient c = base.newBuilder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.corp", 8080)))
.connectTimeout(30, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS)
.build(); Defensive patterns
Strategy: retry
Validate before calling
// Reachability probe before first use of the client:
static boolean canReachBitbucketApi() {
try {
HttpURLConnection c = (HttpURLConnection) URI.create("https://api.bitbucket.org/2.0/").toURL().openConnection();
c.setConnectTimeout(5000);
c.setReadTimeout(10000);
return c.getResponseCode() > 0;
} catch (IOException e) {
return false;
}
}
// If false, fix DNS/proxy/firewall before calling createAccessToken/doGet/doGetWithApiToken. Try / catch
// Since this is a transport-level failure, retry with backoff and preserve the cause:
RuntimeException last = null;
for (int attempt = 1; attempt <= 3; attempt++) {
try {
return doCallSomething();
} catch (IllegalStateException e) {
if ("Error returned by Bitbucket Cloud".equals(e.getMessage()) && e.getCause() instanceof IOException) {
last = e;
sleepBackoff(attempt); // e.g. 1s, 2s, 4s
continue;
}
throw e; // parsed HTTP error — not retryable at transport level
}
}
throw last; Prevention
- Ensure the SonarQube host has reliable egress to api.bitbucket.org:443; test with curl before rollout.
- Configure OkHttp connect/read timeouts large enough for large paginated repository listings.
- Set JVM proxy properties when behind a corporate proxy and restart the server afterwards.
- Install corporate CA certificates into the JVM truststore if TLS interception is in place.
- Watch the Bitbucket Cloud status page; transient outages surface as this transport-level exception.
When it happens
Trigger: Thrown from doCall, called by createAccessToken, doGet and doGetWithApiToken, whenever client.newCall(request).execute() throws IOException while calling api.bitbucket.org or the OAuth token endpoint: unknown host, connect/read timeout, connection reset, or SSL handshake failure.
Common situations: SonarQube server has no egress to api.bitbucket.org (firewall, air-gapped installation); proxy not configured for the JVM; DNS outage; TLS-intercepting proxy with untrusted certificates; Bitbucket Cloud returning a connection-level failure during an outage; response read interrupted by socket timeout on large repository listings.
Related errors
- SonarQube was not able to retrieve resources from external s
- %s for request [%s]: [%s]
- Error returned by Bitbucket Cloud: The OAuth client in the B
- e.getMessage()
- Unable to contact Bitbucket Cloud servers
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/3e7a5fb282b43983.
Report an issue: GitHub.