SonarSource/sonarqube · error · IllegalArgumentException
url must start with http:// or https://
Error message
url must start with http:// or https://
What it means
BitbucketServerRestClient.buildUrl validates the configured Bitbucket server URL before building the REST endpoint. If serverUrl is null or does not start with http:// or https:// (case-insensitive), an IllegalArgumentException with this message is thrown. The library requires a fully-qualified absolute URL for the ALM server setting.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucketserver/BitbucketServerRestClient.java:121
public RepositoryList getRecentRepo(String serverUrl, String token) {
HttpUrl url = buildUrl(serverUrl, "/rest/api/1.0/profile/recent/repos");
return doGet(token, url, body -> buildGson().fromJson(body, RepositoryList.class));
}
public ProjectList getProjects(String serverUrl, String token, @Nullable Integer start, int pageSize) {
String startOrEmpty = Optional.ofNullable(start).map(String::valueOf).orElse("");
HttpUrl url = buildUrl(serverUrl, format("/rest/api/1.0/projects?start=%s&limit=%s", startOrEmpty, pageSize));
return doGet(token, url, body -> buildGson().fromJson(body, ProjectList.class));
}
public BranchesList getBranches(String serverUrl, String token, String projectSlug, String repositorySlug) {
HttpUrl url = buildUrl(serverUrl, format("/rest/api/1.0/projects/%s/repos/%s/branches", projectSlug, repositorySlug));
return doGet(token, url, body -> buildGson().fromJson(body, BranchesList.class));
}
protected static HttpUrl buildUrl(@Nullable String serverUrl, String relativeUrl) {
if (serverUrl == null || !(serverUrl.toLowerCase(ENGLISH).startsWith("http://") || serverUrl.toLowerCase(ENGLISH).startsWith("https://"))) {
throw new IllegalArgumentException("url must start with http:// or https://");
}
return HttpUrl.parse(CS.removeEnd(serverUrl, "/") + relativeUrl);
}
protected <G> G doGet(String token, HttpUrl url, Function<String, G> handler) {
Request request = prepareRequestWithBearerToken(token, GET, url, null);
return doCall(request, handler);
}
protected static Request prepareRequestWithBearerToken(@Nullable String token, String method, HttpUrl url, @Nullable RequestBody body) {
Request.Builder builder = new Request.Builder()
.method(method, body)
.url(url)
.addHeader("x-atlassian-token", "no-check")
.addHeader("Accept", "application/json");
if (!isNullOrEmpty(token)) {
builder.addHeader("Authorization", "Bearer " + token);View on GitHub (pinned to 184c821202)
Solutions
- Set the Bitbucket server URL to an absolute URL including the scheme, e.g. https://bitbucket.example.com (Administration > ALM Integrations, or update almSetting via web API).
- If serverUrl is null, the ALM setting is missing or misnamed — create/verify the Bitbucket ALM configuration bound to the project.
- Strip trailing slashes and any path you expect the client to add; the client appends /rest/api/1.0/... itself.
Example fix
// before: almSetting serverUrl = "bitbucket.mycompany.com" // after: serverUrl = "https://bitbucket.mycompany.com"
Defensive patterns
Strategy: validation
Validate before calling
String serverUrl = /* configured Bitbucket server URL */;
if (serverUrl == null || !(serverUrl.toLowerCase(Locale.ENGLISH).startsWith("http://") || serverUrl.toLowerCase(Locale.ENGLISH).startsWith("https://"))) {
throw new IllegalArgumentException("Bitbucket server URL must be an absolute http(s) URL, got: " + serverUrl);
} Type guard
static boolean isValidServerUrl(String url) {
return url != null && (url.toLowerCase(Locale.ENGLISH).startsWith("http://") || url.toLowerCase(Locale.ENGLISH).startsWith("https://"));
} Prevention
- Always store the Bitbucket base URL with an explicit http:// or https:// scheme.
- Validate the ALM server URL at configuration-save time in the UI/API, not at request time.
- Avoid trailing slashes and relative hostnames in stored settings.
When it happens
Trigger: Calling any BitbucketServerRestClient method (e.g. url(projectSlug, repositorySlug)) when the almSettings/bitbucket serverUrl is null, or set to a scheme-less value like 'my-bitbucket.example.com', 'bitbucket.example.com/', 'ftp://...', or 'localhost:7990'.
Common situations: Administrators entering the Bitbucket Server host without a scheme in project ALM settings; settings imported from old configs or database rows with a null serverUrl; using an env placeholder that resolves to empty; SonarQube instances where the Bitbucket integration was configured before a scheme was required.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- %s is not a valid url
- Invalid Azure URL
- Unable to contact Bitbucket server
- Unable to contact Bitbucket server, got an unexpected respon
- Unexpected response from Bitbucket server
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/7ff8695112591cf7.
Report an issue: GitHub.