apache/druid · error · UnsupportedOperationException

Reverse lookup not allowed.

Error message

Reverse lookup not allowed.

What it means

indexOf performs a reverse lookup (value -> ordinal), which is not implemented for SpectatorHistogramIndexed because SpectatorHistogram values have no cheap equality/ordering suitable for dictionary reversal. Any call throws UnsupportedOperationException.

Source

Thrown at extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramIndexed.java:141

  {
    checkIndex(index);

    NullableOffsetsHeader.Offset offset = offsetsHeader.get(index);
    if (offset == null) {
      return null;
    }

    ByteBuffer copyValueBuffer = valueBuffer.asReadOnlyBuffer();
    copyValueBuffer.position(offset.getStart());
    copyValueBuffer.limit(offset.getStart() + offset.getLength());

    return strategy.fromByteBuffer(copyValueBuffer, offset.getLength());
  }

  @Override
  public int indexOf(@Nullable SpectatorHistogram value)
  {
    throw new UnsupportedOperationException("Reverse lookup not allowed.");
  }

  @Override
  public Iterator<SpectatorHistogram> iterator()
  {
    return IndexedIterable.create(this).iterator();
  }

  @Override
  public long getSerializedSize()
  {
    throw new UnsupportedOperationException("Serialization not supported here");
  }

  @Override
  public void writeTo(WritableByteChannel channel, SegmentFileBuilder fileBuilder)
  {
    throw new UnsupportedOperationException("Serialization not supported here");

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Do not call indexOf on this column type; track dictionary ids alongside selectors instead of looking them up by value.
  2. Refactor the calling code to compare values via the selector interface rather than ordinals.
  3. If a reverse lookup is genuinely needed, use a different column type that supports it.

Example fix

// before
int ordinal = indexed.indexOf(value);
// after
// SpectatorHistogramIndexed cannot reverse-lookup; keep the ordinal from iteration instead.
int ordinal = ordinalTrackedDuringIteration;
Defensive patterns

Strategy: type-guard

Validate before calling

if (indexed instanceof SpectatorHistogramIndexed) { throw new UnsupportedOperationException("reverse lookup unsupported for this column type"); }

Type guard

boolean supportsReverseLookup(Indexed<?> idx) { return !(idx instanceof SpectatorHistogramIndexed); }

Try / catch

try { return indexed.indexOf(value); } catch (UnsupportedOperationException e) { return -1; // fall back to iteration-based id tracking }

Prevention

When it happens

Trigger: Calling indexOf(value) on the histogram column's Indexed object, typically via generic code paths that assume all Indexed implementations support reverse lookup (e.g. certain group-by or filter machinery).

Common situations: Plugging spectator-histogram columns into query paths that do dictionary lookups by value; custom code that iterates selectors and tries to map a histogram back to a dictionary id.

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/aa1ac7ba8d987a93. Report an issue: GitHub.