apache/druid · error · IllegalStateException

Metric[ ] loaded up metric[ ] from disk. File names do…

Error message

Metric[%s] loaded up metric[%s] from disk.  File names do matter.

What it means

When mapping a v8 segment, IndexIO.mapDir loads each metric file and MetricHolder carries the metric name recorded inside the binary. If the internal name does not equal the metric filename, the index is inconsistent and Druid throws ISE, since lookups are by filename and would silently attach data to the wrong metric.

Solutions

  1. Restore the original metric filenames from a clean copy of the segment in deep storage
  2. Re-persist the segment from raw data (or re-run the merge) to regenerate consistent metric files
  3. Do not rename metric files inside segment directories; archive/restore directories atomically
Defensive patterns

Strategy: try-catch

Try / catch

try {
  MMappedIndex idx = indexIO.mapDir(inDir);
} catch (ISE e) {
  if (e.getMessage().contains("File names do matter")) {
    log.error("Corrupt/renamed v8 segment %s: re-fetch from deep storage", inDir);
  }
}

Prevention

When it happens

Trigger: Loading a v8 segment directory where a metric file (e.g. index_0.smoosh entry) was renamed, or the segment was written with mismatched metric order/names in index.drd vs the metric holder data.

Common situations: Hand-edited or partially-copied segment directories; files renamed during custom archival scripts; corrupted/mixed segments after failed manual merge attempts.

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/5aaf43c17c68fddb. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/IndexIO.java:385

          GenericIndexed.STRING_STRATEGY,
          smooshedFiles
      );
      final Interval dataInterval = Intervals.of(SERIALIZER_UTILS.readString(indexBuffer));
      final BitmapSerdeFactory bitmapSerdeFactory = new BitmapSerde.LegacyBitmapSerdeFactory();

      CompressedColumnarLongsSupplier timestamps = CompressedColumnarLongsSupplier.fromByteBuffer(
          smooshedFiles.mapFile(makeTimeFile(inDir, BYTE_ORDER).getName()),
          BYTE_ORDER,
          smooshedFiles
      );

      Map<String, MetricHolder> metrics = Maps.newLinkedHashMap();
      for (String metric : availableMetrics) {
        final String metricFilename = makeMetricFile(inDir, metric, BYTE_ORDER).getName();
        final MetricHolder holder = MetricHolder.fromByteBuffer(smooshedFiles.mapFile(metricFilename));

        if (!metric.equals(holder.getName())) {
          throw new ISE("Metric[%s] loaded up metric[%s] from disk.  File names do matter.", metric, holder.getName());
        }
        metrics.put(metric, holder);
      }

      Map<String, GenericIndexed<ByteBuffer>> dimValueUtf8Lookups = new HashMap<>();
      Map<String, VSizeColumnarMultiInts> dimColumns = new HashMap<>();
      Map<String, GenericIndexed<ImmutableBitmap>> bitmaps = new HashMap<>();

      for (String dimension : IndexedIterable.create(availableDimensions)) {
        ByteBuffer dimBuffer = smooshedFiles.mapFile(makeDimFile(inDir, dimension).getName());
        String fileDimensionName = SERIALIZER_UTILS.readString(dimBuffer);
        Preconditions.checkState(
            dimension.equals(fileDimensionName),
            "Dimension file[%s] has dimension[%s] in it!?",
            makeDimFile(inDir, dimension),
            fileDimensionName
        );

View on GitHub (pinned to 9b90983fd2)