apache/druid · error · IllegalStateException

Lookup[%s] has multiple segments; cannot read

Error message

Lookup[%s] has multiple segments; cannot read

What it means

LookupSegmentWrangler is contractually expected to return zero or one segment per lookup. attach() defensively closes the segment(s) and throws this ISE if more than one segment is returned, since a lookup snapshot must be a single logical segment.

Source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/input/lookup/LookupInputSliceReader.java:88

        segmentWrangler.getSegmentsForIntervals(
            new LookupDataSource(lookupName),
            Intervals.ONLY_ETERNITY
        );

    final Iterator<Segment> segmentIterator = segments.iterator();
    if (!segmentIterator.hasNext()) {
      throw new ISE("Lookup[%s] is not loaded", lookupName);
    }

    final Segment segment = segmentIterator.next();
    if (segmentIterator.hasNext()) {
      // LookupSegmentWrangler always returns zero or one segments, so this code block can't
      // happen. That being said: we'll program defensively anyway.
      CloseableUtils.closeAndSuppressExceptions(
          segment,
          e -> log.warn(e, "Failed to close segment for lookup[%s]", lookupName)
      );
      throw new ISE("Lookup[%s] has multiple segments; cannot read", lookupName);
    }

    final LoadableSegment loadableSegment = AdaptedLoadableSegment.fromUnmanagedSegment(
        segment,
        new SegmentDescriptor(Intervals.ETERNITY, "0", 0),
        StringUtils.format("lookup[%s]", lookupName),
        counters.channel(CounterNames.inputChannel(inputNumber))
    );

    return new PhysicalInputSlice(
        ReadablePartitions.empty(),
        Collections.singletonList(loadableSegment),
        Collections.emptyList()
    );
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the LookupSegmentWrangler implementation in use and fix it to return at most one segment per lookup.
  2. Ensure lookup updates replace the previous segment atomically rather than publishing an additional one.
  3. Report this as a bug with the lookup provider/extension if you use stock Druid components, since stock behavior guarantees 0 or 1 segments.

Example fix

// before (custom wrangler)
return ImmutableList.of(oldSegment, newSegment);
// after
return ImmutableList.of(newSegment); // only the latest snapshot
Defensive patterns

Strategy: try-catch

Try / catch

try {
  reader.attach(buffer);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().contains("multiple segments")) {
    log.error(e, "LookupSegmentWrangler returned multiple segments");
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: attach() iterates the wrangler-returned segments and finds a second one - only possible if a custom/nonstandard LookupSegmentWrangler implementation or a misbehaving lookup provider returns multiple segments.

Common situations: Custom lookup extension or test wrangler returning multiple published lookup segments; a broken in-memory lookup management layer where lookup updates are both old and new visible simultaneously.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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