elastic/elasticsearch · error · UncheckedIOException

Can't walk source {}

Error message

Can't walk source {}

What it means

Wraps any IOException that escapes Files.walkFileTree(sourceRoot, ...) during the sync() method. The walker itself handles NoSuchFileException for .attach_pid files (JVM leftovers) by continuing; every other IOException (including failures from the syncMethod callback propagating up through preVisitDirectory/visitFile) is caught here and rethrown as UncheckedIOException.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java:1388

                    Files.createDirectories(destination.getParent());
                    syncMethod.accept(destination, source);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    if (exc instanceof NoSuchFileException noFileException) {
                        // Ignore these files that are sometimes left behind by the JVM
                        if (noFileException.getFile() != null && noFileException.getFile().contains(".attach_pid")) {
                            LOGGER.info("Ignoring file left behind by JVM: {}", noFileException.getFile());
                            return FileVisitResult.CONTINUE;
                        }
                    }
                    throw exc;
                }
            });
        } catch (IOException e) {
            throw new UncheckedIOException("Can't walk source " + sourceRoot, e);
        }
    }

    private void createConfiguration() {
        String nodeName = nameCustomization.apply(safeName(name));
        Map<String, String> baseConfig = new HashMap<>(defaultConfig);
        if (nodeName != null) {
            baseConfig.put("node.name", nodeName);
        }
        baseConfig.put("path.repo", confPathRepo.toAbsolutePath().toString());
        baseConfig.put("path.data", confPathData.toAbsolutePath().toString());
        baseConfig.put("path.logs", confPathLogs.toAbsolutePath().toString());
        if (Boolean.getBoolean("java.net.preferIPv6Addresses")) {
            baseConfig.put("network.host", "_local:ipv6_");
        }
        baseConfig.put("node.attr.testattr", "test");
        baseConfig.put("node.portsfile", "true");
        baseConfig.put("http.port", httpPort);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Look at the wrapped IOException's cause and file path — it identifies which entry in sourceRoot failed.
  2. Re-extract the distribution (delete the extracted dir and let the build task recreate it).
  3. Verify read permissions on the entire sourceRoot tree (chmod -R+r if needed).
  4. If the real cause is link/copy failure, fix that first (errors 86/87) — this throw is a symptom.
Defensive patterns

Strategy: try-catch

Validate before calling

if (Files.notExists(sourceRoot) || !Files.isReadable(sourceRoot)) {
    throw new IllegalStateException("sourceRoot " + sourceRoot + " missing/unreadable");
}

Try / catch

try {
    Files.walkFileTree(sourceRoot, new SimpleFileVisitor<>() { ... });
} catch (IOException e) {
    throw new UncheckedIOException("Can't walk source " + sourceRoot, e);
}

Prevention

When it happens

Trigger: The visitor throws inside preVisitDirectory/visitFile (e.g. a hard-link or copy failure from syncWithLinks/syncWithCopy bubbles up), or walkFileTree itself cannot read sourceRoot (permissions, sourceRoot deleted mid-walk, broken symlink).

Common situations: The extracted distribution sourceRoot is missing or has restrictive permissions; a symlink inside the distro points nowhere; the underlying link/copy operation failed (see errors 86/87) and propagated through the visitor.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/f0b1747f905f626f. Report an issue: GitHub.