{"record":{"id":"44b920cb6aa22d55","repo":"SonarSource/sonarqube","slug":"could-not-parse-pagination-number","errorCode":null,"errorMessage":"Could not parse pagination number","messagePattern":"Could not parse pagination number","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java","lineNumber":420,"sourceCode":"      String xtotal = headers.get(\"X-Total\");\n      Integer totalProjects = Strings.isEmpty(xtotal) ? null : parseAndGetIntegerHeader(xtotal);\n      return new ProjectList(projectList, returnedPageNumber, returnedPageSize, totalProjects);\n    } catch (JsonSyntaxException e) {\n      throw new IllegalArgumentException(\"Could not parse GitLab answer to search projects. Got a non-json payload as result.\");\n    } catch (IOException e) {\n      logException(url, e);\n      throw new IllegalStateException(e.getMessage(), e);\n    }\n  }\n\n  private static int parseAndGetIntegerHeader(@Nullable String header) {\n    if (header == null) {\n      throw new IllegalArgumentException(\"Pagination data from GitLab response is missing\");\n    } else {\n      try {\n        return Integer.parseInt(header);\n      } catch (NumberFormatException e) {\n        throw new IllegalArgumentException(\"Could not parse pagination number\", e);\n      }\n    }\n  }\n\n  public Set<GsonGroup> getGroups(String gitlabUrl, String token) {\n    return Set.copyOf(executePaginatedQuery(gitlabUrl, token, \"/groups\", resp -> parseJsonList(resp, GITLAB_GROUP)));\n  }\n\n  public Set<GsonUser> getDirectGroupMembers(String gitlabUrl, String token, String groupId) {\n    return getMembers(gitlabUrl, token, format(GITLAB_GROUPS_MEMBERS_ENDPOINT, groupId));\n  }\n\n  public Set<GsonUser> getAllGroupMembers(String gitlabUrl, String token, String groupId) {\n    return getMembers(gitlabUrl, token, format(GITLAB_GROUPS_MEMBERS_ENDPOINT + \"/all\", groupId));\n  }\n\n  private Set<GsonUser> getMembers(String gitlabUrl, String token, String endpoint) {\n    return Set.copyOf(executePaginatedQuery(gitlabUrl, token, endpoint, resp -> parseJsonList(resp, GITLAB_USER)));","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java#L402-L438","documentation":"parseAndGetIntegerHeader parses a pagination header string (X-Page, X-Per-Page, X-Total) into an int. When the header value exists but is not a valid integer, Integer.parseInt throws NumberFormatException, which is wrapped in this IllegalArgumentException (with the cause preserved). GitLab returned malformed pagination metadata.","triggerScenarios":"searchProjects processing a response where X-Page, X-Per-Page, or X-Total is present but non-numeric — e.g. an HTML fragment, an error message, or empty string injected by a proxy.","commonSituations":"Proxy/error pages rewriting header values; a non-GitLab server mimicking endpoints with bogus headers; corrupted intermediary responses; custom middleware adding unexpected header values.","solutions":["Inspect raw response headers (curl -i) to see the malformed pagination value.","Check and fix proxy/middleware that rewrites or adds header values on GitLab responses.","Ensure the configured GitLab URL targets the authentic GitLab API.","If GitLab-side, check instance version and any custom response modifiers."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// pre-validate header values are numeric before processing responses\nboolean numeric = headerValue != null && headerValue.matches(\"\\\\d+\");","typeGuard":null,"tryCatchPattern":"try { ProjectList l = client.searchProjects(...); } catch (IllegalArgumentException e) { /* malformed pagination header: inspect raw headers */ }","preventionTips":["Inspect raw headers with curl -i when pagination parsing fails","Remove/fix middleware that rewrites GitLab response headers","Point integrations at the genuine GitLab API host"],"tags":["gitlab","pagination","http-headers","number-format"],"backgroundTag":"invalid-argument-format","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"}