{"record":{"id":"d1b8d68ac2828966","repo":"SonarSource/sonarqube","slug":"page-size-must-be-0","errorCode":null,"errorMessage":"Page size must be >= 0","messagePattern":"Page size must be >= 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java","lineNumber":123,"sourceCode":"  public void handle(Request wsRequest, Response wsResponse) throws Exception {\n    try (DbSession dbSession = dbClient.openSession(false)) {\n      SearchTemplatesRequest request = new SearchTemplatesRequest()\n        .setQuery(wsRequest.param(Param.TEXT_QUERY))\n        .setPage(wsRequest.paramAsInt(Param.PAGE))\n        .setPageSize(wsRequest.paramAsInt(Param.PAGE_SIZE));\n\n      validatePaginationParameters(request);\n      checkGlobalAdmin(userSession);\n\n      SearchTemplatesWsResponse searchTemplatesWsResponse = buildResponse(load(dbSession, request));\n      writeProtobuf(searchTemplatesWsResponse, wsRequest, wsResponse);\n    }\n  }\n\n  private static void validatePaginationParameters(SearchTemplatesRequest request) {\n    if (request.getPageSize() != null) {\n      if (request.getPageSize() < 0) {\n        throw new IllegalArgumentException(\"Page size must be >= 0\");\n      }\n      if (request.getPageSize() > RESULTS_MAX_SIZE) {\n        throw new IllegalArgumentException(\"Page size must not exceed \" + RESULTS_MAX_SIZE);\n      }\n    }\n  }\n\n  private static void buildDefaultTemplatesResponse(SearchTemplatesWsResponse.Builder response, SearchTemplatesData data) {\n    TemplateIdQualifier.Builder templateUuidQualifierBuilder = TemplateIdQualifier.newBuilder();\n\n    ResolvedDefaultTemplates resolvedDefaultTemplates = data.defaultTemplates();\n    response.addDefaultTemplates(templateUuidQualifierBuilder\n      .setQualifier(ComponentQualifiers.PROJECT)\n      .setTemplateId(resolvedDefaultTemplates.getProject()));\n\n    resolvedDefaultTemplates.getApplication()\n      .ifPresent(viewDefaultTemplate -> response.addDefaultTemplates(\n        templateUuidQualifierBuilder","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java#L105-L141","documentation":"SearchTemplatesAction.validatePaginationParameters rejects a negative ps (page size) parameter for api/permissions/search_templates. Page size is optional, but when supplied it must be a non-negative integer not exceeding RESULTS_MAX_SIZE.","triggerScenarios":"GET api/permissions/search_templates with ps=-1 or any negative page-size value; SDKs or scripts computing page size dynamically (e.g. total-fetched differences) yielding negative numbers.","commonSituations":"Pagination loops that compute remaining items incorrectly and pass negative page sizes; hand-written queries with placeholder values not replaced (ps=-1); copying examples that used invalid values.","solutions":["Pass a non-negative ps value (e.g. ps=100) or omit ps entirely to use the default","Fix the pagination loop so page size is computed as Math.max(0, remaining)","Validate user-supplied page size in your UI before forwarding it to the API"],"exampleFix":"// before\nconst ps = limit - fetched; // can go negative\nawait searchTemplates({ ps });\n\n// after\nconst ps = Math.max(0, Math.min(limit - fetched, 500));\nawait searchTemplates({ ps });","handlingStrategy":"validation","validationCode":"if (ps != null && ps < 0) throw new Error('Page size must be >= 0');\nawait searchTemplates({ ps });","typeGuard":"function isValidPageSize(ps) { return ps == null || (Number.isInteger(ps) && ps >= 0); }","tryCatchPattern":"try { await searchTemplates({ ps }); } catch (e) { if (e.message.includes('Page size must be >= 0')) { return searchTemplates({}); } throw e; }","preventionTips":["Clamp computed page sizes with Math.max(0, n)","Omit ps when you want the server default","Sanitize user input that feeds pagination params"],"tags":["webapi","permissions","pagination","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}