apache/druid · error · UnsupportedOperationException
Reverse lookup not allowed.
Error message
Reverse lookup not allowed.
What it means
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.
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)
Example fix
// before
int idx = fixedIndexed.indexOf(value);
// after
if (fixedIndexed instanceof FixedIndexed && !isSorted(fixedIndexed)) {
int idx = -1;
for (int i = 0; i < fixedIndexed.size(); i++) {
if (Objects.equals(fixedIndexed.get(i), value)) { idx = i; break; }
}
} else {
int idx = fixedIndexed.indexOf(value);
} Defensive patterns
Strategy: validation
Validate before calling
int safeIndexOf(FixedIndexed<?> idx, Object value) {
return idx instanceof FrontCodedIndexed || isSortedIndex(idx)
? idx.indexOf(value)
: linearScan(idx, value);
} Type guard
boolean supportsReverseLookup(FixedIndexed<?> idx) {
// only sorted FixedIndexed instances support indexOf
return isSortedIndex(idx);
} Try / catch
try {
int i = fixedIndexed.indexOf(value);
} catch (UnsupportedOperationException e) {
// fall back to a linear scan over the unsorted index
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot get map view
- Cannot load data from location
- Cannot retrieve map view from lookup
- No field names available
- Aggregator[ ] cannot vectorize
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b5d9628e8c87b65a.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/data/FixedIndexed.java:138
@Override
public T get(int index)
{
Indexed.checkIndex(index, size);
if (hasNull) {
if (index == 0) {
return null;
}
return typeStrategy.read(buffer, valuesOffset + ((index - 1) * width));
} else {
return typeStrategy.read(buffer, valuesOffset + (index * width));
}
}
@Override
public int indexOf(@Nullable T value)
{
if (!isSorted) {
throw new UnsupportedOperationException("Reverse lookup not allowed.");
}
int minIndex = 0;
int maxIndex = size - 1;
while (minIndex <= maxIndex) {
int currIndex = (minIndex + maxIndex) >>> 1;
T currValue = get(currIndex);
int comparison = comparator.compare(currValue, value);
if (comparison == 0) {
return currIndex;
}
if (comparison < 0) {
minIndex = currIndex + 1;
} else {
maxIndex = currIndex - 1;
}
}View on GitHub (pinned to 9b90983fd2)