SonarSource/sonarqube · error · IllegalArgumentException

Could not parse GitLab answer when creating a project access

Error message

Could not parse GitLab answer when creating a project access token. Got a non-json payload as result.

What it means

createProjectAccessToken POSTs to GitLab to create a project access token and parses the reply body into GitlabProjectAccessToken with Gson. If the body is not valid JSON, JsonSyntaxException is caught and IllegalArgumentException 'Could not parse GitLab answer when creating a project access token. Got a non-json payload as result.' is thrown. The token was not created (or its metadata could not be read) because the response was not the expected GitLab JSON.

Source

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

    LOG.debug("create project access token : [{}]", url);
    Request request = new Request.Builder()
      .addHeader(PRIVATE_TOKEN, personalAccessToken)
      .addHeader("Content-Type", MediaTypes.JSON)
      .url(url)
      .post(RequestBody.create(requestJson.getBytes(UTF_8)))
      .build();

    try (Response response = client.newCall(request).execute()) {
      checkResponseIsSuccessful(response, "Could not create GitLab project access token");
      String body = response.body().string();
      // Never log `body` verbatim: the create-token response's "token" field is the newly minted
      // secret itself (CWE-532) — only its non-sensitive metadata is safe to trace.
      GitlabProjectAccessToken token = new GsonBuilder().create().fromJson(body, GitlabProjectAccessToken.class);
      LOG.trace("create project access token result : id=[{}] name=[{}] expires_at=[{}] scopes=[{}]",
        token.getId(), token.getName(), token.getExpiresAt(), token.getScopes());
      return token;
    } catch (JsonSyntaxException e) {
      throw new IllegalArgumentException("Could not parse GitLab answer when creating a project access token. Got a non-json payload as result.");
    } catch (IOException e) {
      logException(url, e);
      throw new IllegalStateException(e.getMessage(), e);
    }
  }

  public Project getProject(String gitlabUrl, String pat, Long gitlabProjectId) {
    String url = format("%s/projects/%s", gitlabUrl, gitlabProjectId);
    LOG.debug("get project : [{}]", url);
    Request request = new Request.Builder()
      .addHeader(PRIVATE_TOKEN, pat)
      .get()
      .url(url)
      .build();

    try (Response response = client.newCall(request).execute()) {
      checkResponseIsSuccessful(response);
      String body = response.body().string();

View on GitHub (pinned to 184c821202)

Solutions

  1. Verify the GitLab base URL resolves to the instance root and that API calls return JSON (curl the endpoint with the PAT).
  2. Check proxies/VPNs/WAFs between SonarQube and GitLab for HTML injection; whitelist the SonarQube server.
  3. Retry the operation — an empty or truncated body may be transient.
  4. Confirm the GitLab version supports the project access tokens API (GitLab 13.x+).

Example fix

// before: URL hits the web UI
url = https://gitlab.example.com/projects/new
// after: correct API root
url = https://gitlab.example.com
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the token-creation endpoint answers JSON before posting
Response probe = call("GET", gitlabUrl + "/api/v4/version", token);
String ct = probe.header("Content-Type", "");
if (!ct.contains("application/json")) throw new IllegalStateException("GitLab API not returning JSON (Content-Type: " + ct + ") — check URL/proxy");

Try / catch

try {
  gitlabClient.createProjectAccessToken(projectId, name, scopes);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Could not parse GitLab answer when creating a project access token")) {
    // inspect raw response via server log / proxy, then retry after fixing URL/proxy
  } else { throw e; }
}

Prevention

When it happens

Trigger: The create project access token call returns a body Gson cannot parse (HTML from a proxy/login page, empty body, or non-JSON error page) after checkResponseIsSuccessful passed, raising the error at GitlabApplicationClient.java:296.

Common situations: Proxy/WAF injecting HTML into the response; GitLab URL misconfigured so a web page rather than the API endpoint answers; GitLab version returning an unexpected body format for the token creation endpoint; truncated response due to network issues.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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