SonarSource/sonarqube · error · IllegalArgumentException

Could not validate GitLab token scopes. Got an unexpected an

Error message

Could not validate GitLab token scopes. Got an unexpected answer.

What it means

Thrown by GitlabApplicationClient.getPersonalAccessTokenInfo when the HTTP call to /personal_access_tokens/self fails with IOException (or checkResponseIsSuccessful maps a non-2xx status to this message). The token's scopes could not be validated.

Source

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

  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) {
      throw new IllegalArgumentException("Could not parse GitLab answer to verify token scopes. Got a non-json payload as result.");
    } catch (IOException e) {
      logException(url, e);
      throw new IllegalArgumentException(errorMessage);
    }
  }

  public void checkWritePermission(String gitlabUrl, String personalAccessToken) {
    String url = format("%s/markdown", gitlabUrl);

    LOG.debug("verify write permission by formating some markdown : [{}]", url);
    Request.Builder builder = new Request.Builder()
      .url(url)
      .addHeader(PRIVATE_TOKEN, personalAccessToken)
      .addHeader("Content-Type", MediaTypes.JSON)
      .post(RequestBody.create("{\"text\":\"validating write permission\"}".getBytes(UTF_8)));

    Request request = builder.build();

    String errorMessage = "Could not validate GitLab write permission. Got an unexpected answer.";
    try (Response response = client.newCall(request).execute()) {
      checkResponseIsSuccessful(response, errorMessage);

View on GitHub (pinned to 184c821202)

Solutions

  1. Verify the personal access token is valid and has the 'api' scope
  2. Check the GitLab version supports /personal_access_tokens/self (16+); upgrade or check the logged IOException for details
  3. Ensure network/TLS connectivity from the SonarQube server to GitLab

Example fix

// before: PAT scopes = [read_user] (insufficient)
// after: recreate PAT with scopes ['api'] in GitLab user settings
Defensive patterns

Strategy: validation

Validate before calling

const res = await fetch(`${gitlabUrl}/api/v4/personal_access_tokens/self`, { headers: { 'PRIVATE-TOKEN': token } });
if (!res.ok) throw new Error(`Token scopes check failed: HTTP ${res.status}`);
const info = await res.json();
if (!info.scopes.includes('api')) throw new Error('Token lacks api scope');

Try / catch

try { gitlabClient.getPersonalAccessTokenInfo(url, token); } catch (IllegalArgumentException e) { log.error("Scopes validation failed: check token validity/scopes and GitLab version", e); }

Prevention

When it happens

Trigger: getPersonalAccessTokenInfo: execute()/body().string() throws IOException, or the GitLab API returns a non-successful HTTP status (401 invalid token, 404 endpoint not present in older GitLab, 403 missing scope).

Common situations: Token revoked or without 'api' scope; GitLab version without the endpoint (404); network/TLS failure between SonarQube and GitLab.

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/80aee737aae48d74. Report an issue: GitHub.