apache/druid · error · IllegalArgumentException
Path[ ] is not within directory[ ]
Error message
Path[%s] is not within directory[%s]
What it means
In resolveFileWithinDirectory, if the supplied path string cannot be parsed as a Path (InvalidPathException), Druid wraps that failure as IllegalArgumentException with the same 'Path[%s] is not within directory[%s]' message, treating unparseable paths as un-resolvable within the directory.
Solutions
- Sanitize/encode the path string before passing it (escape or hash illegal characters)
- Catch IllegalArgumentException and surface a user-facing message about the invalid identifier
- Validate identifiers used in file names at ingestion time
- Use Path.of on the components rather than a pre-joined string to localize the failure
Example fix
// before
File f = FileUtils.resolveFileWithinDirectory(dir, untrustedName);
// after
String safeName = untrustedName.replaceAll("[\0\\/<>:\"|?*]", "_");
File f = FileUtils.resolveFileWithinDirectory(dir, safeName); Defensive patterns
Strategy: validation
Validate before calling
boolean safe = name != null && !name.contains("\0")
&& name.chars().noneMatch(c -> c < 32)
&& Path.of(name) != null; // may still throw InvalidPathException on illegal chars Type guard
boolean isValidRelativeName(String s) {
try {
return s != null && !Path.of(s).isAbsolute() && !s.contains("..");
} catch (InvalidPathException e) {
return false;
}
} Try / catch
try {
return FileUtils.resolveFileWithinDirectory(dir, path);
} catch (IllegalArgumentException e) {
throw new BadRequestException("Invalid path: " + path, e);
} Prevention
- Sanitize or hash untrusted identifiers before using them as file names
- Test file-name handling with platform-illegal characters
- Reject control characters and NUL bytes at input boundaries
- Normalize identifiers to a safe charset (e.g. [A-Za-z0-9._-])
When it happens
Trigger: Calling FileUtils.resolveFileWithinDirectory(directory, path) where path contains invalid characters for the filesystem (e.g. NUL byte, illegal chars on Windows) so Path.of(path) throws InvalidPathException.
Common situations: Segment/lock file names built from untrusted or mangled input; Windows-illegal characters in identifiers used as file names; corrupted metadata producing garbage paths.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Skipping deep storage directory kill: relative path must…
- Access-Check-Result
- <authResult.getErrorMessage()>
- authResult.getErrorMessage()
- authResult.getErrorMessage()
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/e1e83f792a16f742.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java:462
// Not expected.
throw new ISE("System property java.io.tmpdir is not set, cannot create temporary directories");
}
return new File(parentDirectory).toPath();
}
/**
* Resolves {@code path} below {@code directory}, rejecting absolute paths and parent traversal that would escape it.
* This is intended for paths containing externally supplied identifiers.
*/
public static File resolveFileWithinDirectory(final File directory, final String path)
{
final Path normalizedDirectory = directory.toPath().toAbsolutePath().normalize();
final Path childPath;
try {
childPath = Path.of(path);
}
catch (InvalidPathException e) {
throw new IAE(e, "Path[%s] is not within directory[%s]", path, directory);
}
if (childPath.isAbsolute()) {
throw new IAE("Path[%s] is not within directory[%s]", path, directory);
}
final Path resolvedPath = normalizedDirectory.resolve(childPath).normalize();
if (!resolvedPath.startsWith(normalizedDirectory)) {
throw new IAE("Path[%s] is not within directory[%s]", path, directory);
}
return resolvedPath.toFile();
}
@SuppressForbidden(reason = "Files#createTempDirectory")
public static File createTempDirInLocation(final Path parentDirectory, @Nullable final String prefix)
{
try {
final Path tmpPath = Files.createTempDirectory(
parentDirectory,
prefix == null || prefix.isEmpty() ? "druid" : prefixView on GitHub (pinned to 9b90983fd2)