{"record":{"id":"648a1fd979698ed5","repo":"apache/druid","slug":"invalid-partition-number-d","errorCode":null,"errorMessage":"Invalid partition number [%d]","messagePattern":"Invalid partition number \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/frame/processor/OutputChannel.java","lineNumber":66,"sourceCode":"  private volatile MemoryAllocator frameMemoryAllocator;\n\n  private final Supplier<ReadableFrameChannel> readableChannelSupplier;\n  private final int partitionNumber;\n\n  private OutputChannel(\n      @Nullable final WritableFrameChannel writableChannel,\n      @Nullable final MemoryAllocator frameMemoryAllocator,\n      final Supplier<ReadableFrameChannel> readableChannelSupplier,\n      final int partitionNumber\n  )\n  {\n    this.writableChannel = writableChannel;\n    this.frameMemoryAllocator = frameMemoryAllocator;\n    this.readableChannelSupplier = readableChannelSupplier;\n    this.partitionNumber = partitionNumber;\n\n    if (partitionNumber < 0 && partitionNumber != WritableFrameChannel.NO_PARTITION) {\n      throw new IAE(\"Invalid partition number [%d]\", partitionNumber);\n    }\n  }\n\n  /**\n   * Creates an output channel pair, where the readable channel is not usable until writing is complete.\n   *\n   * @param writableChannel         writable channel for producer\n   * @param frameMemoryAllocator    memory allocator for producer to use while writing frames to the channel\n   * @param readableChannelSupplier readable channel for consumer. May be called multiple times, so you should wrap this\n   *                                in {@link Suppliers#memoize} if needed.\n   * @param partitionNumber         partition number, if any; may be {@link WritableFrameChannel#NO_PARTITION} if unknown\n   */\n  public static OutputChannel pair(\n      final WritableFrameChannel writableChannel,\n      final MemoryAllocator frameMemoryAllocator,\n      final Supplier<ReadableFrameChannel> readableChannelSupplier,\n      final int partitionNumber\n  )","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/frame/processor/OutputChannel.java#L48-L84","documentation":"OutputChannel wraps a writable/readable frame channel pair with a partition number. Valid partition numbers are nonnegative, except the special sentinel NO_PARTITION (a negative reserved constant) meaning 'no partitioning'. Any other negative number is rejected by the constructor with IAE.","triggerScenarios":"Calling `new OutputChannel(..., -1, ...)` or with a negative partition number computed by subtraction (e.g. partitionIndex - 1 at index 0), where NO_PARTITION was intended but the sentinel constant wasn't used.","commonSituations":"Off-by-one in partition counters; using a magic negative value like -1 that does not match WritableFrameChannel.NO_PARTITION; deserializing partition numbers from config where they came out negative.","solutions":["Use WritableFrameChannel.NO_PARTITION explicitly instead of a hand-written negative number.","Fix the arithmetic producing the negative partition number (guard partitionIndex before decrementing).","Validate partition numbers before constructing OutputChannel when they come from external input."],"exampleFix":"// before\nnew OutputChannel(writable, allocator, supplier, partitionIndex - 1);\n// after\nint partition = partitionIndex > 0 ? partitionIndex - 1 : WritableFrameChannel.NO_PARTITION;\nnew OutputChannel(writable, allocator, supplier, partition);","handlingStrategy":"validation","validationCode":"if (partitionNumber < 0 && partitionNumber != WritableFrameChannel.NO_PARTITION) {\n  throw new IllegalArgumentException(\"Invalid partition number: \" + partitionNumber);\n}","typeGuard":"boolean validPartition(int p) { return p >= 0 || p == WritableFrameChannel.NO_PARTITION; }","tryCatchPattern":"try {\n  out = new OutputChannel(writable, allocator, supplier, partition);\n} catch (IllegalArgumentException e) {\n  // fall back to NO_PARTITION sentinel\n}","preventionTips":["Always use the WritableFrameChannel.NO_PARTITION constant for 'no partition'.","Guard decrement-based partition counters.","Validate externally supplied partition numbers."],"tags":["java","argument-validation","partitioning"],"backgroundTag":"argument-out-of-range","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}