{"record":{"id":"1a1796560c6f2eb0","repo":"SonarSource/sonarqube","slug":"uuids-can-not-be-empty","errorCode":null,"errorMessage":"uuids can not be empty","messagePattern":"uuids can not be empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/file/ExportLineHashesStep.java","lineNumber":117,"sourceCode":"      \" order by created_at, uuid\";\n    PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, format(sql, wildCardStringFor(uuids)));\n    try {\n      int i = 1;\n      for (String uuid : uuids) {\n        stmt.setString(i, uuid);\n        i++;\n      }\n      return stmt;\n    } catch (Exception e) {\n      DatabaseUtils.closeQuietly(stmt);\n      throw e;\n    }\n  }\n\n  private static String wildCardStringFor(List<String> uuids) {\n    switch (uuids.size()) {\n      case 0:\n        throw new IllegalArgumentException(\"uuids can not be empty\");\n      case 1:\n        return \"?\";\n      default:\n        return createWildCardStringFor(uuids);\n    }\n  }\n\n  private static String createWildCardStringFor(List<String> uuids) {\n    int size = (uuids.size() * 2) - 1;\n    char[] res = new char[size];\n    for (int j = 0; j < size; j++) {\n      if (j % 2 == 0) {\n        res[j] = '?';\n      } else {\n        res[j] = ',';\n      }\n    }\n    return new String(res);","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/file/ExportLineHashesStep.java#L99-L135","documentation":"wildCardStringFor builds a SQL IN placeholder list for a batch of file uuids; an empty list cannot produce a valid IN clause, so it throws IllegalArgumentException. This is an internal pre-condition: the caller should never invoke it with zero uuids.","triggerScenarios":"Internally: calling wildCardStringFor(List.of()) — in practice only from a bug in ExportLineHashesStep's batching loop iterating an empty uuid batch, or when overridden/test code passes an empty list.","commonSituations":"Rarely seen in production; mostly surfaces from code modifications or custom forks that change the batching logic, or unit tests exercising the helper with empty input.","solutions":["Guard the caller: skip the query when the uuid batch list is empty.","If you modified the batching code, restore the non-empty-batch invariant before calling the helper.","If seen in stock SonarQube, report it with the CE task logs as a bug."],"exampleFix":"// before\nString placeholders = wildCardStringFor(uuidBatch);\n// after\nif (!uuidBatch.isEmpty()) {\n  String placeholders = wildCardStringFor(uuidBatch);\n  ...\n}","handlingStrategy":"validation","validationCode":"if (uuids == null || uuids.isEmpty()) {\n  return; // skip query entirely, no IN clause possible\n}","typeGuard":"boolean isNonEmptyBatch(List<String> uuids) {\n  return uuids != null && !uuids.isEmpty();\n}","tryCatchPattern":"try {\n  placeholders = wildCardStringFor(uuids);\n} catch (IllegalArgumentException e) {\n  logger.warn(\"Empty uuid batch, skipping query\");\n}","preventionTips":["Always skip SQL IN queries when the id batch is empty","Chunk id lists before building placeholders","Cover the batching loop with a unit test for the empty-input edge case"],"tags":["sql","precondition","export","sonarqube"],"backgroundTag":"empty-required-field","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"}