SonarSource/sonarqube · error · IllegalArgumentException

Could not validate GitLab token. Got an unexpected answer.

Error message

Could not validate GitLab token. Got an unexpected answer.

What it means

Thrown by GitlabApplicationClient.checkToken when the HTTP request to the GitLab /user endpoint fails with an IOException (network-level failure). Note this same message is also used by checkResponseIsSuccessful for non-successful HTTP statuses, and the IOException is logged before rethrowing.

Source

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

    String url = format("%s/user", gitlabUrl);

    LOG.debug("get current user : [{}]", url);
    Request.Builder builder = new Request.Builder()
      .addHeader(PRIVATE_TOKEN, personalAccessToken)
      .url(url)
      .get();

    Request request = builder.build();

    String errorMessage = "Could not validate GitLab token. Got an unexpected answer.";
    try (Response response = client.newCall(request).execute()) {
      checkResponseIsSuccessful(response, errorMessage);
      return GsonUser.parse(response.body().string());
    } catch (JsonSyntaxException e) {
      throw new IllegalArgumentException("Could not parse GitLab answer to verify token. Got a non-json payload as result.");
    } catch (IOException e) {
      logException(url, e);
      throw new IllegalArgumentException(errorMessage);
    }
  }

  public GsonPersonalAccessTokenInfo getPersonalAccessTokenInfo(String gitlabUrl, String personalAccessToken) {
    String url = format("%s/personal_access_tokens/self", gitlabUrl);

    LOG.debug("get personal access token info : [{}]", url);
    Request request = new Request.Builder()
      .addHeader(PRIVATE_TOKEN, personalAccessToken)
      .url(url)
      .get()
      .build();

    String errorMessage = "Could not validate GitLab token scopes. Got an unexpected answer.";
    try (Response response = client.newCall(request).execute()) {
      checkResponseIsSuccessful(response, errorMessage);
      return GsonPersonalAccessTokenInfo.parseOne(response.body().string());
    } catch (JsonSyntaxException e) {

View on GitHub (pinned to 184c821202)

Solutions

  1. Test connectivity from the SonarQube host: curl -H 'PRIVATE-TOKEN: <token>' <gitlabUrl>/user
  2. If the token is wrong/revoked you may instead see this via a non-2xx status: verify the token has 'api' scope and is still valid
  3. Add the GitLab TLS certificate to the JVM truststore and fix the gitlabUrl

Example fix

// before: token without 'api' scope -> 403 handled as failure
// after: create a GitLab PAT with scope 'api' and re-enter it in ALM settings
Defensive patterns

Strategy: validation

Validate before calling

curl -sS -o /dev/null -w '%{http_code}' -H "PRIVATE-TOKEN: $TOKEN" "$GITLAB_URL/api/v4/user"  # expect 200 before configuring

Try / catch

try { gitlabClient.checkToken(url, token); } catch (IllegalArgumentException e) { log.error("Token/network validation failed: verify token validity, 'api' scope, and connectivity", e); }

Prevention

When it happens

Trigger: checkToken: client.newCall(request).execute() or response.body().string() throws IOException — host unreachable, DNS failure, TLS handshake error, timeout, or connection reset.

Common situations: SonarQube server cannot reach GitLab; self-signed certificate not trusted; gitlabUrl mistyped; GitLab API outage.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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