{"record":{"id":"cae3956664df39a1","repo":"SonarSource/sonarqube","slug":"could-not-parse-gitlab-answer-to-verify-read-permi","errorCode":null,"errorMessage":"Could not parse GitLab answer to verify read permission. Got a non-json payload as result.","messagePattern":"Could not parse GitLab answer to verify read permission\\. Got a non-json payload as result\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java","lineNumber":113,"sourceCode":"  private void checkProjectAccess(@Nullable String gitlabUrl, @Nullable String personalAccessToken, String errorMessage) {\n    String url = format(\"%s/projects\", gitlabUrl);\n\n    LOG.debug(\"get projects : [{}]\", url);\n    Request.Builder builder = new Request.Builder()\n      .url(url)\n      .get();\n\n    if (personalAccessToken != null) {\n      builder.addHeader(PRIVATE_TOKEN, personalAccessToken);\n    }\n\n    Request request = builder.build();\n\n    try (Response response = client.newCall(request).execute()) {\n      checkResponseIsSuccessful(response, errorMessage);\n      Project.parseJsonArray(response.body().string());\n    } catch (JsonSyntaxException e) {\n      throw new IllegalArgumentException(\"Could not parse GitLab answer to verify read permission. Got a non-json payload as result.\");\n    } catch (IOException e) {\n      logException(url, e);\n      throw new IllegalArgumentException(errorMessage);\n    }\n  }\n\n  private static void logException(String url, IOException e) {\n    String errorMessage = format(\"Gitlab API call to [%s] failed with error message : [%s]\", url, e.getMessage());\n    LOG.info(errorMessage, e);\n  }\n\n  public GsonUser checkToken(String gitlabUrl, String personalAccessToken) {\n    String url = format(\"%s/user\", gitlabUrl);\n\n    LOG.debug(\"get current user : [{}]\", url);\n    Request.Builder builder = new Request.Builder()\n      .addHeader(PRIVATE_TOKEN, personalAccessToken)\n      .url(url)","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java#L95-L131","documentation":"Thrown by GitlabApplicationClient.checkProjectAccess when the GitLab API returns a 2xx response but the body cannot be parsed as the expected JSON project array (JsonSyntaxException). SonarQube uses the parsed projects to verify the token's read permission on a project.","triggerScenarios":"checkReadPermission or checkUrl -> checkProjectAccess gets an HTTP 200 whose body is not valid JSON (HTML error page, empty body, proxy interstitial), causing Gson JsonSyntaxException in Project.parseJsonArray.","commonSituations":"gitlabUrl points to a non-GitLab server or a reverse proxy returning HTML; wrong path behind a proxy; GitLab returns an unexpected empty 200 body.","solutions":["Verify the configured GitLab URL points at the actual GitLab instance root (no trailing path or proxy page)","Test the endpoint manually: curl -H 'PRIVATE-TOKEN: <token>' <gitlabUrl>/projects?membership=true","Check for a proxy/load balancer rewriting responses to HTML error or login pages"],"exampleFix":"// before: gitlabUrl = \"https://example.com/gitlab/\" (proxied HTML)\n// after: gitlabUrl = \"https://gitlab.example.com\";","handlingStrategy":"try-catch","validationCode":"curl -sS -o /dev/null -w '%{content_type}' -H \"PRIVATE-TOKEN: $TOKEN\" \"$GITLAB_URL/api/v4/projects?membership=true\"  # must be application/json","typeGuard":null,"tryCatchPattern":"try { gitlabClient.checkReadPermission(url, token, project); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"non-json\")) { verifyGitlabUrlAndProxy(url); } }","preventionTips":["Point gitlabUrl at the GitLab root, not a proxied or path-prefixed page returning HTML","Whitelist SonarQube server IP in proxies/WAFs so real JSON reaches it","Smoke-test the GitLab endpoint with curl after any infrastructure change"],"tags":["gitlab","json","http-response","parsing"],"backgroundTag":"invalid-json-response","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}