{"record":{"id":"b5d9628e8c87b65a","repo":"apache/druid","slug":"reverse-lookup-not-allowed-b5d962","errorCode":null,"errorMessage":"Reverse lookup not allowed.","messagePattern":"Reverse lookup not allowed\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/FixedIndexed.java","lineNumber":138,"sourceCode":"  @Override\n  public T get(int index)\n  {\n    Indexed.checkIndex(index, size);\n    if (hasNull) {\n      if (index == 0) {\n        return null;\n      }\n      return typeStrategy.read(buffer, valuesOffset + ((index - 1) * width));\n    } else {\n      return typeStrategy.read(buffer, valuesOffset + (index * width));\n    }\n  }\n\n  @Override\n  public int indexOf(@Nullable T value)\n  {\n    if (!isSorted) {\n      throw new UnsupportedOperationException(\"Reverse lookup not allowed.\");\n    }\n    int minIndex = 0;\n    int maxIndex = size - 1;\n    while (minIndex <= maxIndex) {\n      int currIndex = (minIndex + maxIndex) >>> 1;\n\n      T currValue = get(currIndex);\n      int comparison = comparator.compare(currValue, value);\n      if (comparison == 0) {\n        return currIndex;\n      }\n\n      if (comparison < 0) {\n        minIndex = currIndex + 1;\n      } else {\n        maxIndex = currIndex - 1;\n      }\n    }","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/FixedIndexed.java#L120-L156","documentation":"FixedIndexed only supports reverse lookup (indexOf) when the underlying values are sorted. Calling indexOf on an instance created with isSorted=false has no meaningful binary-search result, so it throws UnsupportedOperationException immediately before any search is attempted.","triggerScenarios":"Calling indexOf(value) on a FixedIndexed whose reader (e.g. FrontCodedIndexed or another FixedIndexed built from an unsorted dictionary) was opened with isSorted=false; unsorted FixedIndexed instances come from writers that wrote values in non-sorted order.","commonSituations":"Generic code that assumes every Indexed supports indexOf (e.g. dimension dictionary lookups, filters, or group-by code paths) hitting an unsorted index produced by a newer column format or a writer that skipped sorting; custom code reading segment columns directly.","solutions":["Only call indexOf on FixedIndexed instances known to be sorted (check the isSorted flag or the writer that produced the column)","For unsorted indexes, do a linear scan comparing values instead of indexOf","Ensure the writer produced sorted, unique values so the resulting FixedIndexed is sorted","Upgrade Druid if your column format should produce sorted indexes (newer writers sort values)"],"exampleFix":"// before\nint idx = fixedIndexed.indexOf(value);\n// after\nif (fixedIndexed instanceof FixedIndexed && !isSorted(fixedIndexed)) {\n  int idx = -1;\n  for (int i = 0; i < fixedIndexed.size(); i++) {\n    if (Objects.equals(fixedIndexed.get(i), value)) { idx = i; break; }\n  }\n} else {\n  int idx = fixedIndexed.indexOf(value);\n}","handlingStrategy":"validation","validationCode":"int safeIndexOf(FixedIndexed<?> idx, Object value) {\n  return idx instanceof FrontCodedIndexed || isSortedIndex(idx)\n      ? idx.indexOf(value)\n      : linearScan(idx, value);\n}","typeGuard":"boolean supportsReverseLookup(FixedIndexed<?> idx) {\n  // only sorted FixedIndexed instances support indexOf\n  return isSortedIndex(idx);\n}","tryCatchPattern":"try {\n  int i = fixedIndexed.indexOf(value);\n} catch (UnsupportedOperationException e) {\n  // fall back to a linear scan over the unsorted index\n}","preventionTips":["Check the isSorted property of the index before calling indexOf","Always write dictionary columns with sorted, unique values","Prefer the standard reader factories so isSorted is set correctly","Avoid generic code paths that assume indexOf is available on every Indexed"],"tags":["unsupported-operation","indexed","lookup"],"backgroundTag":"unsupported-operation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}