{"record":{"id":"a45214bdc5e9f1b4","repo":"apache/druid","slug":"cannot-remove-non-integer-from-integer-bitset","errorCode":null,"errorMessage":"Cannot remove non Integer from integer BitSet","messagePattern":"Cannot remove non Integer from integer BitSet","errorType":"validation","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/collections/IntegerSet.java","lineNumber":112,"sourceCode":"    }\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 {\n      throw new ClassCastException(\"Cannot remove non Integer from integer BitSet\");\n    }\n  }\n\n  @Override\n  public boolean containsAll(Collection<?> c)\n  {\n    Iterator<?> it = c.iterator();\n    while (it.hasNext()) {\n      if (!this.contains(it.next())) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  @Override\n  public boolean addAll(Collection<? extends Integer> c)\n  {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/collections/IntegerSet.java#L94-L130","documentation":"IntegerSet only stores Integer elements; remove(Object) performs an instanceof check and throws ClassCastException when the argument is any other type. Because Set.remove takes Object, the compiler cannot catch wrong-type removals, so this runtime guard enforces the element type.","triggerScenarios":"Calling remove() with a non-Integer object such as a Long, String, or primitive-boxed other type (e.g. remove(Long.valueOf(5))), or removeAll() with a collection of Longs that looks like ints but boxes to Long.","commonSituations":"Mixing numeric types: data read from JSON/protobuf arrives as Long, or a List<Long> of IDs is passed to an IntegerSet API; also raw-typed collections losing generic type safety.","solutions":["Ensure the argument is boxed Integer: convert with ((Number) value).intValue() before removing","Convert collections of other numeric types: list.stream().map(Number::intValue).collect(Collectors.toList())","Fix generic types so the collection is typed List<Integer>/Set<Integer>, letting the compiler catch mismatches","If Long values are the norm, switch to a bitmap/collection that supports longs"],"exampleFix":"// before\nset.remove(longValue); // ClassCastException\n// after\nset.remove(Integer.valueOf(longValue.intValue()));","handlingStrategy":"type-guard","validationCode":"if (!(o instanceof Integer)) { o = ((Number) o).intValue(); }\nset.remove(o);","typeGuard":"static Integer toInteger(Object o) { return (o instanceof Integer) ? (Integer) o : (o instanceof Number ? ((Number) o).intValue() : null); }","tryCatchPattern":"try { set.remove(o); } catch (ClassCastException e) { /* convert numeric types before removing */ }","preventionTips":["Type collections as Set<Integer> so the compiler catches mismatches","Convert Long/other numeric IDs via intValue() before bitmap-set operations","Beware JSON/protobuf numeric decoding yielding Long"],"tags":["java","bitmap","set","class-cast"],"backgroundTag":"type-mismatch","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"}