{"record":{"id":"586f99f6bb084a88","repo":"SonarSource/sonarqube","slug":"could-not-validate-gitlab-read-permission-got-an","errorCode":null,"errorMessage":"Could not validate GitLab read permission. Got an unexpected answer.","messagePattern":"Could not validate GitLab read permission\\. Got an unexpected answer\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java","lineNumber":116,"sourceCode":"    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)\n      .get();\n\n    Request request = builder.build();","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java#L98-L134","documentation":"Thrown by GitlabApplicationClient.checkProjectAccess when the HTTP call to the GitLab projects API throws IOException — connection failure, timeout, or stream read error. The IOException is logged and rethrown as IllegalArgumentException with the generic validation message.","triggerScenarios":"checkReadPermission or checkUrl -> checkProjectAccess: OkHttp client.newCall(request).execute() or response.body().string() throws IOException (unreachable host, DNS failure, TLS error, timeout).","commonSituations":"Firewall blocks SonarQube server to GitLab; wrong hostname or port in gitlabUrl; TLS certificate not trusted by SonarQube's JVM; GitLab temporarily down.","solutions":["Confirm network connectivity from the SonarQube server to the GitLab host (curl the URL from the server)","Fix the gitlabUrl hostname/port and import the GitLab TLS certificate into the JVM truststore if self-signed","Check the logged message 'Gitlab API call to [%s] failed...' for the underlying IOException cause"],"exampleFix":"// before: gitlabUrl = \"https://gitlab.internal:8443\" (port blocked)\n// after: gitlabUrl = \"https://gitlab.internal\"; // open firewall / correct port","handlingStrategy":"try-catch","validationCode":"curl -sS -m 10 -H \"PRIVATE-TOKEN: $TOKEN\" \"$GITLAB_URL/api/v4/user\" > /dev/null && echo reachable  # run from the SonarQube host","typeGuard":null,"tryCatchPattern":"try { gitlabClient.checkReadPermission(url, token, project); } catch (IllegalArgumentException e) { log.error(\"GitLab connectivity problem: check URL, firewall, and TLS truststore\", e); }","preventionTips":["Verify DNS, firewall, and outbound HTTPS from the SonarQube server to GitLab before configuring","Import self-signed GitLab CA certificates into the JVM truststore","Use hostnames resolvable from the SonarQube container/server, not localhost unless co-located"],"tags":["gitlab","network","io","http-request"],"backgroundTag":"http-request-failed","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"}