apache/druid · error · SegmentLoadingException

Unable to load from local directory [%s]

Error message

Unable to load from local directory [%s]

What it means

LocalDataSegmentPuller.getSegmentFiles throws SegmentLoadingException when it fails to extract a locally stored segment that is a .tgz/.tar.gz archive. The underlying IOException (missing file, permissions, corrupt archive, full disk) is wrapped with the source file path. This is the local-filesystem deep-storage loader, so it means the segment archive on disk could not be expanded into the target directory.

Source

Thrown at server/src/main/java/org/apache/druid/segment/loading/LocalDataSegmentPuller.java:156

            continue;
          }

          final File newFile = new File(dir, oldFile.getName());
          final FileUtils.LinkOrCopyResult linkOrCopyResult = FileUtils.linkOrCopy(oldFile, newFile);
          link = link && linkOrCopyResult == FileUtils.LinkOrCopyResult.LINK;
          result.addFile(newFile);
        }
        log.info(
            "%s %d bytes from [%s] to [%s]",
            link ? "Linked" : "Copied",
            result.size(),
            sourceFile.getAbsolutePath(),
            dir.getAbsolutePath()
        );
        return result;
      }
      catch (IOException e) {
        throw new SegmentLoadingException(e, "Unable to load from local directory [%s]", sourceFile.getAbsolutePath());
      }
    } else if (CompressionUtils.isZip(sourceFile.getName())) {
      try {
        final FileUtils.FileCopyResult result = CompressionUtils.unzip(
            Files.asByteSource(sourceFile),
            dir,
            shouldRetryPredicate(),
            false
        );
        log.info(
            "Unzipped %d bytes from [%s] to [%s]",
            result.size(),
            sourceFile.getAbsolutePath(),
            dir.getAbsolutePath()
        );
        return result;
      }
      catch (IOException e) {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Verify the source file exists and is readable by the Druid process user (ls -l on the path in the message).
  2. Test archive integrity with `tar -tzf <file>`; re-ingest or re-replicate the segment if it is corrupt.
  3. Check disk space and write permission on the output directory.
  4. Remove/re-download the bad segment copy: disable the segment and let Druid re-replicate from another replica.

Example fix

// before (manual copy skipped nested files)
cp -r /mnt/old-deepstorage/druid/segments/wikipedia/2015/ /mnt/deepstorage/druid/segments/wikipedia/2015/
// after (copy full segment dir, verify archive)
rsync -a /mnt/old-deepstorage/druid/segments/wikipedia/2015/01/ /mnt/deepstorage/druid/segments/wikipedia/2015/01/
tar -tzf /mnt/deepstorage/druid/segments/wikipedia/2015/01/2015-01-01T00:00:00.000Z_2015-01-02T00:00:00.000Z_day/0/index.zip
Defensive patterns

Strategy: try-catch

Validate before calling

final File f = new File((String) segment.getLoadSpec().get("path"));
if (!f.isFile() || !f.canRead()) throw new IllegalStateException("segment source unreadable: " + f);
if (!f.getName().endsWith(".tar.gz") && !f.getName().endsWith(".tgz")) throw new IllegalStateException("not a tgz archive: " + f);

Type guard

boolean isTgzSegment(Map<String,Object> loadSpec) {
  Object p = loadSpec.get("path");
  return p instanceof String && ((String) p).matches(".*\\.(tar\\.gz|tgz)$");
}

Try / catch

try {
  puller.getSegmentFiles(segment, outDir);
} catch (SegmentLoadingException e) {
  log.error(e, "failed to extract local segment %s; marking replica bad", segment.getId());
  // let Druid re-replicate from another replica
}

Prevention

When it happens

Trigger: DataSegment whose loadSpec type is 'local' and whose file name ends in .tgz/.tar.gz, when CompressionUtils.tarGz to the output dir throws IOException during getSegmentFiles.

Common situations: Manually copied or trimmed druid segment directories on historical nodes; segments corrupted by incomplete writes or disk-full; files moved without their archive; read-permission loss after user change; corrupting archives by editing deep-storage files by hand.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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