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
- Verify the GitLab base URL resolves to the instance root and that API calls return JSON (curl the endpoint with the PAT).
- Check proxies/VPNs/WAFs between SonarQube and GitLab for HTML injection; whitelist the SonarQube server.
- Retry the operation — an empty or truncated body may be transient.
- 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
- Keep proxies/WAFs from returning HTML for API paths.
- Confirm the GitLab version supports project access tokens (13.x+).
- Retry transient failures; empty bodies are often network truncation.
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
- Could not validate GitLab write permission. Got an unexpecte
- Could not parse GitLab answer to verify token. Got a non-jso
- Could not validate GitLab token. Got an unexpected answer.
- SonarQube was not able to retrieve resources from external s
- Could not parse GitLab answer to verify read permission. Got
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/d6c996289a71ed5e.
Report an issue: GitHub.