SonarSource/sonarqube · warning · GitlabServerException

GitLab API rate limit exceeded. Try again later.

Error message

GitLab API rate limit exceeded. Try again later.

What it means

checkResponseIsSuccessful translates GitLab's HTTP 429 (Too Many Requests) into GitlabServerException 'GitLab API rate limit exceeded. Try again later.' SonarQube made more GitLab API requests than the instance allows per window; the call failed client-throttling, not because of configuration.

Source

Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java:220

  protected static void checkResponseIsSuccessful(Response response) throws IOException {
    checkResponseIsSuccessful(response, "GitLab Merge Request did not happen, please check your configuration");
  }

  protected static void checkResponseIsSuccessful(Response response, String errorMessage) throws IOException {
    if (!response.isSuccessful()) {
      String body = response.body().string();
      LOG.error("Gitlab API call to [{}] failed with {} http code. gitlab response content : [{}]", response.request().url(), response.code(), body);
      if (isTokenRevoked(response, body)) {
        throw new GitlabServerException(response.code(), "Your GitLab token was revoked");
      } else if (isTokenExpired(response, body)) {
        throw new GitlabServerException(response.code(), "Your GitLab token is expired");
      } else if (isInsufficientScope(response, body)) {
        throw new GitlabServerException(response.code(), "Your GitLab token has insufficient scope");
      } else if (response.code() == HTTP_FORBIDDEN) {
        throw new GitlabServerException(response.code(), "Forbidden access to GitLab. Verify your token's permissions and IP restrictions.");
      } else if (response.code() == HTTP_TOO_MANY_REQUESTS) {
        throw new GitlabServerException(response.code(), "GitLab API rate limit exceeded. Try again later.");
      } else if (response.code() == HTTP_UNAUTHORIZED) {
        throw new GitlabServerException(response.code(), "Invalid personal access token");
      } else if (response.isRedirect()) {
        throw new GitlabServerException(response.code(), "Request was redirected, please provide the correct URL");
      } else {
        throw new GitlabServerException(response.code(), errorMessage);
      }
    }
  }

  private static boolean isTokenRevoked(Response response, String body) {
    if (response.code() == HTTP_UNAUTHORIZED) {
      try {
        Optional<GsonError> gitlabError = GsonError.parseOne(body);
        return gitlabError.map(GsonError::getErrorDescription).map(description -> description.contains("Token was revoked")).orElse(false);
      } catch (JsonParseException e) {
        // nothing to do
      }

View on GitHub (pinned to 184c821202)

Solutions

  1. Wait for the rate-limit window to reset and retry the operation.
  2. Reduce parallelism: import/analyze projects in smaller batches or stagger CI jobs.
  3. Raise rate limits in GitLab (Admin Area > Settings > Network > User and IP rate limits) or on the reverse proxy.
  4. Ensure SonarQube traffic is authenticated (authenticated users get higher limits than anonymous).

Example fix

// before: import all 500 projects at once
parallelImport(projects);
// after: batch with delay
projects.stream().collect(batching(50)).forEach(batch -> { importBatch(batch); sleep(backoff); });
Defensive patterns

Strategy: retry

Try / catch

catch (GitlabServerException e) {
  if ("GitLab API rate limit exceeded. Try again later.".equals(e.getMessage())) {
    long wait = Math.min(60, (long) Math.pow(2, attempt)) * 1000L; // exponential backoff, max 60s
    Thread.sleep(wait);
    retry();
  } else { throw e; }
}

Prevention

When it happens

Trigger: Any GitLab API call via checkResponseIsSuccessful (checkProjectAccess, checkToken, getPersonalAccessTokenInfo, checkWritePermission, createProjectAccessToken) receives 429 at GitlabApplicationClient.java:220 — typically during bulk imports or CI-heavy periods with many concurrent analyses.

Common situations: Large onboarding importing many GitLab projects at once; many CI jobs starting analyses simultaneously; GitLab instance or reverse proxy (nginx) with low rate limits; shared NAT making many SonarQube requests appear from one IP.

Related errors


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