{"record":{"id":"4b94ac9aa9e1b222","repo":"apache/druid","slug":"cannot-have-empty-worker-set","errorCode":null,"errorMessage":"Cannot have empty worker set","messagePattern":"Cannot have empty worker set","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/input/stage/ReadablePartition.java","lineNumber":45,"sourceCode":"\n/**\n * Represents an output partition associated with a particular stage. Each partition is readable from one or\n * more workers.\n */\npublic class ReadablePartition\n{\n  private final int stageNumber;\n  private final IntSortedSet workerNumbers;\n  private final int partitionNumber;\n\n  private ReadablePartition(final int stageNumber, final IntSortedSet workerNumbers, final int partitionNumber)\n  {\n    this.stageNumber = stageNumber;\n    this.workerNumbers = workerNumbers;\n    this.partitionNumber = partitionNumber;\n\n    if (workerNumbers.isEmpty()) {\n      throw new IAE(\"Cannot have empty worker set\");\n    }\n  }\n\n  /**\n   * Returns an output partition that is striped across {@code numWorkers} workers.\n   */\n  public static ReadablePartition striped(final int stageNumber, final int numWorkers, final int partitionNumber)\n  {\n    final IntAVLTreeSet workerNumbers = new IntAVLTreeSet();\n    for (int i = 0; i < numWorkers; i++) {\n      workerNumbers.add(i);\n    }\n\n    return new ReadablePartition(stageNumber, workerNumbers, partitionNumber);\n  }\n\n  /**\n   * Returns an output partition that is striped across a set of {@code workerNumbers}.","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/input/stage/ReadablePartition.java#L27-L63","documentation":"ReadablePartition records which workers hold a given input partition; an empty worker set is meaningless because MSQ needs at least one worker to read each partition. The constructor validates this with an IAE.","triggerScenarios":"Constructing ReadablePartition (directly in tests or via shuffle-spec/partition assignment code) with an empty workerNumbers set - e.g. when partition assignment logic assigns no workers because maxNumSlices is 0 or the worker list was empty.","commonSituations":"Custom shuffle strategies or unit tests passing an empty ImmutableSet/ImmutableList of workers; cluster had zero workers so the assignment produced empty sets.","solutions":["Ensure the worker assignment code only creates ReadablePartitions for partitions actually assigned to >= 1 worker.","Verify the MSQ cluster has at least one available worker (middleManager/indexer capacity) before submitting queries.","In tests, pass a non-empty worker set, e.g. ImmutableSet.of(0)."],"exampleFix":"// before\nnew ReadablePartition(stageNumber, ImmutableSet.of(), partitionNumber);\n// after\nnew ReadablePartition(stageNumber, ImmutableSet.of(0), partitionNumber);","handlingStrategy":"validation","validationCode":"if (workerNumbers == null || workerNumbers.isEmpty()) {\n  throw new IllegalArgumentException(\"workerNumbers must be non-empty\");\n}\nReadablePartition p = new ReadablePartition(stageNumber, workerNumbers, partitionNumber);","typeGuard":null,"tryCatchPattern":"try {\n  return new ReadablePartition(stageNumber, workerNumbers, partitionNumber);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().equals(\"Cannot have empty worker set\")) {\n    log.warn(\"Skipping partition with no assigned workers\");\n    return null;\n  }\n  throw e;\n}","preventionTips":["Filter out partitions with no worker assignment before constructing ReadablePartition.","Verify cluster worker capacity before submitting MSQ queries.","Use non-empty worker sets in unit tests."],"tags":["msq","validation","empty-collection","worker-assignment"],"backgroundTag":"empty-required-field","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}