apache/druid · warning
Skipping deep storage directory kill: relative path is empty
Error message
Skipping deep storage directory kill: relative path is empty
What it means
constructHdfsDeletePath validates the segment's relative path before building an HDFS delete Path. If the relative path is null or empty it logs this warning and returns null, causing the kill to be skipped rather than attempting a dangerous or meaningless delete of the storage root.
Source
Thrown at extensions-core/hdfs-storage/src/main/java/org/apache/druid/storage/hdfs/HdfsDataSegmentKiller.java:183
final FileSystem fs = dirToDelete.getFileSystem(config);
if (!fs.exists(dirToDelete)) {
return;
}
log.info("Deleting deep storage directory[%s]", dirToDelete);
if (!fs.delete(dirToDelete, true)) {
throw new IOException("Failed to delete deep storage directory[" + dirToDelete + "].");
}
}
/**
* Construct a path to delete from HDFS. Returns null if the path is invalid.
* Replicates how {@link HdfsDataSegmentPusher#pushToPath} handles ':', by replacing that with '_'.
*/
@Nullable
private Path constructHdfsDeletePath(String relativePath)
{
if (Strings.isNullOrEmpty(relativePath)) {
log.warn("Skipping deep storage directory kill: relative path is empty");
return null;
}
if (relativePath.charAt(0) == '/') {
log.warn("Skipping deep storage directory kill: relative path must not be absolute, got [%s]", relativePath);
return null;
}
if (relativePath.indexOf('\\') >= 0) {
log.warn("Skipping deep storage directory kill: backslash not allowed in path [%s]", relativePath);
return null;
}
for (String segment : StringUtils.splitPreserveAllTokens(relativePath, '/')) {
if (segment.isEmpty() || "..".equals(segment)) {
log.warn("Skipping deep storage directory kill: invalid path[%s]", relativePath);
return null;
}
}
if (storageDirectory == null) {View on GitHub (pinned to 9b90983fd2)
Solutions
- Inspect the offending segment's loadSpec in metadata store to find why the path is empty
- Re-push or re-ingest the affected segments so a valid relative path is stored
- Skip the kill for such segments; the guard is intentional protection against deleting the whole storage directory
Example fix
// before
if (Strings.isNullOrEmpty(relativePath)) { log.warn("Skipping deep storage directory kill: relative path is empty"); return null; }
// after
if (Strings.isNullOrEmpty(relativePath)) {
log.warnEvents("Skipping deep storage directory kill: relative path is empty for segment [%s]", segment.getIdentifier());
return null;
} Defensive patterns
Strategy: validation
Validate before calling
if (segmentPath == null || segmentPath.isEmpty()) {
throw new IllegalArgumentException("segment relative path must not be empty");
} Type guard
static boolean hasNonEmptyRelativePath(DataSegment s) {
Object p = s.getLoadSpec().get("path");
return p instanceof String && !((String) p).isEmpty();
} Prevention
- Validate segment loadSpecs on ingestion
- Watch for segments pushed by custom adapters
- Re-push segments with empty paths instead of killing them
When it happens
Trigger: A DataSegment whose loadSpec path (relative portion after the storage directory) is empty — typically a segment with a malformed or minimal loadSpec passed to dirToDelete/kill.
Common situations: Segments loaded from old Druid versions or external ingestion that wrote segments without a proper path, or custom deep-storage adapters producing segments with empty paths.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Skipping deep storage directory kill: relative path must not
- Skipping deep storage directory kill: backslash not allowed
- Skipping deep storage directory kill: invalid path[%s]
- Segment path [%s] does not exist
- Skipping deep storage directory kill: storage directory not
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6f40a4bbe0e41caf.
Report an issue: GitHub.