SonarSource/sonarqube · error · BitbucketServerException
Error 404. The requested Bitbucket server is unreachable.
Error message
Error 404. The requested Bitbucket server is unreachable.
What it means
BitbucketServerRestClient.handleHttpErrorIfAny maps HTTP response codes to exceptions. When the Bitbucket Server REST call returns 404 (HTTP_NOT_FOUND), it throws BitbucketServerException(404, "Error 404. The requested Bitbucket server is unreachable."). Despite the wording, it means the server responded but the requested path/resource was not found — most often a wrong URL, wrong project/repo slug, or a proxy stripping the path.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucketserver/BitbucketServerRestClient.java:190
protected static void validateResponseBody(boolean isSuccessful, String bodyString) {
if (isSuccessful) {
try {
buildGson().fromJson(bodyString, Object.class);
} catch (JsonParseException e) {
LOG.info(UNEXPECTED_RESPONSE_FROM_BITBUCKET_SERVER + " : [{}]", bodyString);
throw new IllegalArgumentException(UNEXPECTED_RESPONSE_FROM_BITBUCKET_SERVER, e);
}
}
}
protected static void handleHttpErrorIfAny(boolean isSuccessful, int httpCode, String bodyString) {
if (!isSuccessful) {
String errorMessage = getErrorMessage(bodyString);
LOG.info(UNABLE_TO_CONTACT_BITBUCKET_SERVER + ": {} {}", httpCode, errorMessage);
if (httpCode == HTTP_UNAUTHORIZED) {
throw new BitbucketServerException(HTTP_UNAUTHORIZED, "Invalid personal access token");
} else if (httpCode == HTTP_NOT_FOUND) {
throw new BitbucketServerException(HTTP_NOT_FOUND, "Error 404. The requested Bitbucket server is unreachable.");
}
throw new IllegalArgumentException(UNABLE_TO_CONTACT_BITBUCKET_SERVER);
}
}
protected static boolean equals(@Nullable MediaType first, @Nullable MediaType second) {
String s1 = convertMediaTypeToString(first);
String s2 = convertMediaTypeToString(second);
return s1 != null && s1.equals(s2);
}
private static String convertMediaTypeToString(@Nullable MediaType mediaType) {
return Optional.ofNullable(mediaType)
.map(MediaType::toString)
.map(s -> s.toLowerCase(ENGLISH).replace(" ", ""))
.orElse(null);
}
View on GitHub (pinned to 184c821202)
Solutions
- Verify the Bitbucket Server URL in Administration > ALM Integrations > Bitbucket Server: it must be the server base URL including the context path (e.g. https://bitbucket.example.com/bitbucket), with no trailing path to the API
- Check that the project/repo slug used by the DevOps platform binding exactly matches the Bitbucket repository slug
- Test the URL manually: curl -k -u <user>:<token> <url>/rest/api/1.0/projects — if this 404s, the URL is wrong
- Confirm a proxy/firewall is not returning its own 404 page; inspect the errorMessage logged by the client for the actual 404 body
Example fix
// before (wrong: includes API path or omits context path)
almSetting.setUrl("https://bitbucket.example.com/rest/api/1.0");
// after
correctUrl = "https://bitbucket.example.com" + (hasContextPath ? "/bitbucket" : "");
almSetting.setUrl(correctUrl); Defensive patterns
Strategy: try-catch
Validate before calling
// Java: pre-check before calling the client
URL u = new URL(bitbucketServerUrl);
HttpURLConnection c = (HttpURLConnection) new URL(u, "/rest/api/1.0/projects?limit=1").openConnection();
c.setRequestProperty("Authorization", "Bearer " + token);
if (c.getResponseCode() == 404) throw new IllegalStateException("Wrong Bitbucket Server URL or missing context path"); Type guard
// Java: sanity-check the configured URL shape before calling
static boolean isPlausibleBitbucketUrl(String url) {
try {
URI uri = new URI(url);
return uri.getScheme() != null && (uri.getScheme().equals("https") || uri.getScheme().equals("http")) && uri.getHost() != null;
} catch (URISyntaxException e) { return false; }
} Try / catch
try {
client.getRepo(projectKey, repoSlug);
} catch (BitbucketServerException e) {
if (e.getStatus() == 404) {
// wrong URL, context path, or repo slug — re-check configuration and binding
throw new ConfigurationException("Bitbucket server URL or repository binding is wrong: " + e.getMessage());
}
throw e;
} Prevention
- Always configure the Bitbucket Server base URL including the context path (e.g. .../bitbucket), never the API path
- Cross-check repo slugs/keys used in bindings against Bitbucket exactly (case-sensitive)
- Test the URL with a direct curl to /rest/api/1.0/projects before saving the integration
- Watch server logs: the 404 body message is logged at INFO by the client
When it happens
Trigger: Any REST call made through getBodyString (e.g. validateUrl, validateToken, project/repo lookups during ALM import or PR decoration) where Bitbucket Server answers HTTP 404.
Common situations: Typo in the configured Bitbucket Server URL (e.g. missing or extra context path like /bitbucket); repository was renamed/deleted or the repo slug case is wrong; SonarQube pointed at the wrong base URL so /rest/api/* paths 404; a reverse proxy returns 404 for unknown hosts; SonarQube configured against Bitbucket Cloud instead of Bitbucket Server.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- SonarQube was not able to retrieve resources from external s
- Unable to contact Bitbucket Cloud servers
- Error while executing a call to %s. Return code %s. Error me
- %s for request [%s]: [%s]
- Unable to contact Bitbucket Cloud servers: Configure the OAu
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/8097e74f9d05e755.
Report an issue: GitHub.