apache/druid · error · SegmentLoadingException
Unable to unzip file [%s]
Error message
Unable to unzip file [%s]
What it means
LocalDataSegmentPuller.getSegmentFiles throws SegmentLoadingException when a locally stored segment ending in .zip fails to unzip with an IOException. The segment's index.zip could not be extracted to the target directory, usually because the archive is corrupt, truncated, or unreadable.
Source
Thrown at server/src/main/java/org/apache/druid/segment/loading/LocalDataSegmentPuller.java:175
}
} 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) {
throw new SegmentLoadingException(e, "Unable to unzip file [%s]", sourceFile.getAbsolutePath());
}
} else if (CompressionUtils.isGz(sourceFile.getName())) {
final File outFile = new File(dir, CompressionUtils.getGzBaseName(sourceFile.getName()));
final FileUtils.FileCopyResult result = CompressionUtils.gunzip(
Files.asByteSource(sourceFile),
outFile,
shouldRetryPredicate()
);
log.info(
"Gunzipped %d bytes from [%s] to [%s]",
result.size(),
sourceFile.getAbsolutePath(),
outFile.getAbsolutePath()
);
return result;
} else {
throw new SegmentLoadingException("Do not know how to handle source [%s]", sourceFile.getAbsolutePath());
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Check `unzip -t <segment index.zip>` to confirm corruption.
- Verify free disk space on the Druid segment cache directory.
- Re-push the segment (re-run the task or use the segments REST API to reset) or re-copy it from a healthy replica.
- Ensure the Druid process has read access to the source zip and write access to the target dir.
Example fix
// before: extracting a zip corrupted by scp without binary mode scp oldhost:/ds/druid/.../index.zip /ds/druid/.../index.zip // after: verify and re-copy preserving binary rsync -a --checksum oldhost:/ds/druid/.../index.zip /ds/druid/.../ unzip -t /ds/druid/.../index.zip
Defensive patterns
Strategy: try-catch
Validate before calling
final File zip = new File((String) segment.getLoadSpec().get("path"));
if (!zip.isFile() || zip.length() == 0 || !zip.canRead()) throw new IllegalStateException("index.zip missing or unreadable: " + zip); Type guard
boolean isZipSegment(Map<String,Object> loadSpec) {
Object p = loadSpec.get("path");
return p instanceof String && ((String) p).endsWith(".zip");
} Try / catch
try {
puller.getSegmentFiles(segment, outDir);
} catch (SegmentLoadingException e) {
log.error(e, "corrupt zip for %s; discarding local copy", segment.getId());
FileUtils.deleteQuietly(outDir);
} Prevention
- Always copy segment files in binary mode (rsync/scp -p), never text mode.
- Verify archive integrity (unzip -t) after manual deep-storage copies.
- Ensure adequate free disk space for extraction before load.
- Keep healthy replicas so corrupt copies can be re-downloaded.
When it happens
Trigger: DataSegment with local loadSpec and zip-compressed segment file when CompressionUtils.unzip throws during getSegmentFiles.
Common situations: Truncated index.zip from an interrupted push; disk-full during extraction; copy tools that corrupted binary data (e.g. text-mode transfer); permission changes on the deep-storage directory.
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
- Unable to load from local directory [%s]
- e.getMessage()
- Input stream is null
- Failed to fetch google cloud storage object from bucket [%s]
- Failed to fetch google cloud storage object from bucket [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/dc012cceb6994e3d.
Report an issue: GitHub.