{"record":{"id":"c004a2fb5ca60504","repo":"apache/druid","slug":"only-positive-integers-or-zero-can-be-added","errorCode":null,"errorMessage":"Only positive integers or zero can be added","messagePattern":"Only positive integers or zero can be added","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/collections/IntegerSet.java","lineNumber":93,"sourceCode":"  @Override\n  public Object[] toArray()\n  {\n    Integer[] retval = new Integer[mutableBitmap.size()];\n    int pos = 0;\n    for (Integer i : this) {\n      retval[pos++] = i;\n    }\n    return retval;\n  }\n\n  @Override\n  public boolean add(Integer integer)\n  {\n    if (null == integer) {\n      throw new NullPointerException(\"BitSet cannot contain null values\");\n    }\n    if (integer < 0) {\n      throw new IllegalArgumentException(\"Only positive integers or zero can be added\");\n    }\n    boolean isSet = mutableBitmap.get(integer);\n    mutableBitmap.add(integer.intValue());\n    return !isSet;\n  }\n\n  @Override\n  public boolean remove(Object o)\n  {\n    if (o == null) {\n      throw new NullPointerException(\"BitSet cannot contain null values\");\n    }\n    if (o instanceof Integer) {\n      Integer integer = (Integer) o;\n      boolean isSet = mutableBitmap.get(integer);\n      mutableBitmap.remove(integer);\n      return isSet;\n    } else {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/collections/IntegerSet.java#L75-L111","documentation":"IntegerSet is a Set<Integer> backed by a bitmap, and bitmaps can only index non-negative offsets. add() rejects null elements and any negative Integer because there is no valid bitmap slot for them. The check happens before mutating the bitmap, so the set is unchanged when this is thrown.","triggerScenarios":"Calling add() with a negative Integer (e.g. add(-1)), or passing a value resulting from arithmetic that underflows below zero. Null arguments throw the related NullPointerException instead.","commonSituations":"Computing offsets/deltas that can go negative (e.g. current - previous on unordered data), deserializing user or external data containing negative IDs, off-by-one index arithmetic, or autoboxing an int expression that was assumed non-negative.","solutions":["Validate the integer is >= 0 before calling add(), and clamp or skip negatives","Fix the upstream computation producing negative values (ordering, off-by-one, delta logic)","If negative values are legitimate data, use a different collection (HashSet<Integer>) instead of IntegerSet","Handle null separately since add(null) throws NullPointerException, not this error"],"exampleFix":"// before\nset.add(delta); // throws if delta < 0\n// after\nif (delta != null && delta >= 0) {\n  set.add(delta);\n}","handlingStrategy":"validation","validationCode":"if (value == null) throw new NullPointerException(\"value required\");\nif (value < 0) throw new IllegalArgumentException(\"value must be >= 0: \" + value);\nset.add(value);","typeGuard":"static boolean isAddable(Integer v) { return v != null && v >= 0; }","tryCatchPattern":"try { set.add(value); } catch (NullPointerException e) { /* null element */ } catch (IllegalArgumentException e) { /* negative element */ }","preventionTips":["Validate sign before inserting into bitmap-backed sets","Watch for subtraction-based index math that can go negative","Remember IntegerSet is null-hostile: filter nulls first"],"tags":["java","bitmap","set","argument-validation"],"backgroundTag":"invalid-argument-value","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"}