elastic/elasticsearch · error · IllegalArgumentException

extra config file destination can't be relative, was {} for

Error message

extra config file destination can't be relative, was {} for {}

What it means

Thrown by the single-arg extraConfigFile(destination, from) overload when the destination string contains '..'. The check blocks path traversal: destinations are resolved against the config dir, so '..' would escape it and potentially overwrite arbitrary files in the distro. IllegalArgumentException because it is a misuse of the API, not a runtime cluster fault.

Source

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

            if (Files.exists(destination) == false) {
                fileSystemOperations.copy(spec -> {
                    if (module.get().getName().toLowerCase().endsWith(".zip")) {
                        spec.from(archiveOperations.zipTree(module));
                    } else if (module.get().isDirectory()) {
                        spec.from(module);
                    } else {
                        throw new IllegalArgumentException("Not a valid module " + module + " for " + this);
                    }
                    spec.into(destination);
                });
            }
        }
    }

    @Override
    public void extraConfigFile(String destination, File from) {
        if (destination.contains("..")) {
            throw new IllegalArgumentException("extra config file destination can't be relative, was " + destination + " for " + this);
        }
        extraConfigFiles.put(destination, from);
    }

    @Override
    public void extraConfigFile(String destination, File from, PropertyNormalization normalization) {
        if (destination.contains("..")) {
            throw new IllegalArgumentException("extra config file destination can't be relative, was " + destination + " for " + this);
        }
        extraConfigFiles.put(destination, from, normalization);
    }

    @Override
    public void extraJarFiles(FileCollection from) {
        extraJarConfigurations.add(from);
    }

    @Override

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use a destination path that stays under the config directory (no '..').
  2. If you need a file outside config/, use a different hook (e.g. extraJarFiles for lib, or write a custom task).
  3. If '..' appears inside a legitimate filename, rename the file to avoid the substring.
  4. On Windows, use forward slashes or a plain filename; avoid mixing separators that introduce '..'.

Example fix

// before: tries to escape config dir
extraConfigFile('../elasticsearch.yml', myFile)
// after: keep destination under config/
extraConfigFile('elasticsearch.yml', myFile)
Defensive patterns

Strategy: validation

Validate before calling

static String safeExtraConfigDest(String dest) {
    if (dest.contains("..")) {
        throw new IllegalArgumentException("extra config dest must not contain '..': " + dest);
    }
    return dest;
}
// Use: node.extraConfigFile(safeExtraConfigDest("log4j2.xml"), file);

Type guard

// True when destination stays within the config tree (no traversal)
static boolean isSafeConfigDest(String dest) {
    return !dest.contains("..") && !dest.startsWith("/");
}

Prevention

When it happens

Trigger: Calling extraConfigFile('../elasticsearch.yml', file), extraConfigFile('certs/../../scripts/x', file), or any destination string containing the literal substring '..' (the check is naive: it flags '..' anywhere, including inside filenames like 'my..file').

Common situations: Deliberate attempt to write outside config/. Accidental absolute path or Windows backslash causing the '..' substring. Filename containing '..' (false positive due to the substring check).

Related errors


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