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

  1. 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).
  2. If serverUrl is null, the ALM setting is missing or misnamed — create/verify the Bitbucket ALM configuration bound to the project.
  3. 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

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


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