apache/kafka · error · ConfigException
Path normalisedPath could not be resolved
Error message
Path normalisedPath could not be resolved
What it means
Thrown by AllowedPaths.getAllowedPaths() when Path.toRealPath() raises an IOException during resolution of an otherwise valid, existing absolute path. This is the fallback ConfigException (with the underlying IOException as cause) for filesystem-level resolution failures that the existence check did not catch, such as broken symlinks encountered mid-resolution or permission errors reading directory metadata.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/config/internals/AllowedPaths.java:56
this.allowedPaths = getAllowedPaths(configValue);
}
private List<Path> getAllowedPaths(String configValue) {
if (configValue != null && !configValue.isEmpty()) {
List<Path> allowedPaths = new ArrayList<>();
Arrays.stream(configValue.split(",")).forEach(b -> {
Path normalisedPath = Paths.get(b).normalize();
if (!normalisedPath.isAbsolute()) {
throw new ConfigException("Path " + normalisedPath + " is not absolute");
} else if (!Files.exists(normalisedPath)) {
throw new ConfigException("Path " + normalisedPath + " does not exist");
} else {
try {
allowedPaths.add(normalisedPath.toRealPath());
} catch (IOException e) {
throw new ConfigException("Path " + normalisedPath + " could not be resolved", e);
}
}
});
return allowedPaths;
}
return null;
}
/**
* Checks if the given {@code path} resides in the configured {@code allowed.paths}.
* If {@code allowed.paths} is not configured, the given Path is returned as allowed.
* @param path the Path to check if allowed
* @return Path that can be accessed or null if the given Path does not reside in the configured {@code allowed.paths}.
*/
public Path parseUntrustedPath(String path) {
Path parsedPath = Paths.get(path);View on GitHub (pinned to c31c9215e1)
Solutions
- Inspect the underlying IOException cause in the log (ConfigException wraps it) to see the exact I/O failure.
- Resolve or remove broken symlinks along the path: readlink -f <path> && ls -la.
- Grant the JVM user read+execute permissions on every directory in the chain.
- Replace the symlinked entry with the canonical real target path in allowed.paths.
Example fix
# before ln -s /mnt/missing /etc/kafka/secrets allowed.paths=/etc/kafka/secrets # after # fix or recreate the symlink target ln -sfn /mnt/present/secrets /etc/kafka/secrets allowed.paths=/mnt/present/secrets
Defensive patterns
Strategy: try-catch
Validate before calling
// Best-effort probe of toRealPath() before AllowedPaths construction:
for (String raw : configValue.split(",")) {
Path p = Paths.get(raw.trim()).normalize();
try {
p.toRealPath(); // surfaces broken symlinks / permission issues early
} catch (IOException e) {
throw new IllegalArgumentException(
"allowed.paths entry '" + p + "' cannot be resolved: " + e.getMessage(), e);
}
} Try / catch
try {
AllowedPaths ap = new AllowedPaths(configValue);
} catch (ConfigException e) {
if (e.getMessage().endsWith("could not be resolved")
&& e.getCause() instanceof IOException) {
// broken symlink / I/O fault: log cause, retry, or fall back to a known-good path
} else { throw e; }
} Prevention
- Avoid broken or circular symlinks inside allowed.paths trees; resolve them at provisioning time.
- Ensure the JVM process has read+execute permission on every path component leading to the configured entry.
- Treat toRealPath failures as environmental (filesystem race, NFS hiccup): prefer retry-with-backoff or fail-fast over silent skip.
When it happens
Trigger: AllowedPaths construction with an allowed.paths entry that is absolute and exists at the top level but contains a broken symlink, a cyclic symlink chain, or an intermediate directory the JVM cannot read/stat. toRealPath() throws IOException, wrapped as ConfigException.
Common situations: allowed.paths entry points at a symlink whose target is missing or unreachable. Container layers where intermediate mount points are not stat-able by the JVM user. NFS/network filesystem hiccups during startup. SELinux/AppArmor denying stat on an intermediate directory.
Related errors
- Path normalisedPath does not exist
- Path normalisedPath is not absolute
- Could not load config provider class or one of its dependenc
- Could not list directory {dir}
- Could not read file {path} for property {fileName}
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/eecc49a2367e6747.json.
Report an issue: GitHub.