elastic/elasticsearch · error · GradleException
Failed to read {exclusionsFileAbsolutePath}
Error message
Failed to read {exclusionsFileAbsolutePath} What it means
Thrown by DockerSupportService.getLinuxExclusionList() when reading the Docker exclusion list file fails. The file path is configured via the DOCKER_ON_LINUX_EXCLUSIONS_FILE parameter, set by DockerSupportPlugin to .ci/dockerOnLinuxExclusions relative to the settings directory. The file contains newline-separated Linux distribution IDs that should be excluded from Docker tasks. IOException is wrapped in GradleException.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportService.java:279
return excluded;
}
return false;
}
private List<String> getLinuxExclusionList() {
File exclusionsFile = getParameters().getExclusionsFile();
if (exclusionsFile.exists()) {
try {
return Files.readAllLines(exclusionsFile.toPath())
.stream()
.map(String::trim)
.filter(line -> (line.isEmpty() || line.startsWith("#")) == false)
.collect(Collectors.toList());
} catch (IOException e) {
throw new GradleException("Failed to read " + exclusionsFile.getAbsolutePath(), e);
}
} else {
return Collections.emptyList();
}
}
// visible for testing
static String deriveId(Map<String, String> values) {
return values.get("ID") + "-" + values.get("VERSION_ID");
}
// visible for testing
static Map<String, String> parseOsRelease(final List<String> osReleaseLines) {
final Map<String, String> values = new HashMap<>();
osReleaseLines.stream().map(String::trim).filter(line -> (line.isEmpty() || line.startsWith("#")) == false).forEach(line -> {
final String[] parts = line.split("=", 2);
final String key = parts[0];View on GitHub (pinned to db6a809a66)
Solutions
- Check the file permissions and ownership: ls -la .ci/dockerOnLinuxExclusions.
- If the file is a broken symlink, recreate it from git: git checkout -- .ci/dockerOnLinuxExclusions.
- Verify the file is readable by the Gradle daemon process user: test -r .ci/dockerOnLinuxExclusions && echo readable.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight check on exclusions file
File exclusionsFile = new File(settingsDir, ".ci/dockerOnLinuxExclusions");
if (exclusionsFile.exists() && !exclusionsFile.canRead()) {
throw new GradleException("Exclusions file exists but cannot be read: " + exclusionsFile);
} Prevention
- Ensure .ci/dockerOnLinuxExclusions is committed with read permissions (644).
- Add a pre-build check that verifies the file is readable in CI.
- Avoid symlinks for this file to prevent broken-link issues.
When it happens
Trigger: getLinuxExclusionList() is called (transitively from isExcludedOs()), the exclusions file exists (File.exists() returns true), but Files.readAllLines throws IOException. This can happen due to permission denied, the file being a broken symlink, or concurrent modification during read.
Common situations: The .ci/dockerOnLinuxExclusions file has restrictive permissions (e.g., 000 or owned by a different user). The file is a symlink pointing to a non-existent target (exists() follows symlinks and returns true for broken symlinks in some JVM versions). A CI agent has a corrupted checkout where the file is partially written.
Related errors
- Failed to read /etc/os-release
- Failed to write marker file
- Failed to read branches.json from: {}
- Unable to create reaper JAR output directory {}
- Failed to write unicast_hosts for {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/dbc9804c6ce4aaa5.
Report an issue: GitHub.