elastic/elasticsearch · error · PolicyValidationException

'relative_path' [{}] must be relative

Error message

'relative_path' [{}] must be relative

What it means

Thrown when `relative_path` resolves to an absolute path on the running filesystem. The relative_path branch is reserved for paths expressed relative to the `relative_to` base dir; an absolute value would double-anchor and is rejected — absolute paths must use the `path` field instead.

Source

Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java:283

            }

            if (relativeTo != null && relativePathAsString == null) {
                throw new PolicyValidationException("'relative_to' may only be used with 'relative_path'");
            }

            if (settingBaseDirAsString != null && pathSetting == null) {
                throw new PolicyValidationException("'basedir_if_relative' may only be used with 'path_setting'");
            }

            final FileData fileData;
            if (relativePathAsString != null) {
                if (relativeTo == null) {
                    throw new PolicyValidationException("files entitlement with a 'relative_path' must specify 'relative_to'");
                }
                BaseDir baseDir = parseBaseDir(relativeTo);
                Path relativePath = Path.of(relativePathAsString);
                if (FileUtils.isAbsolutePath(relativePathAsString)) {
                    throw new PolicyValidationException("'relative_path' [" + relativePathAsString + "] must be relative");
                }
                fileData = FileData.ofRelativePath(relativePath, baseDir, mode);
            } else if (pathAsString != null) {
                Path path = Path.of(pathAsString);
                if (FileUtils.isAbsolutePath(pathAsString) == false) {
                    throw new PolicyValidationException("'path' [" + pathAsString + "] must be absolute");
                }
                fileData = FileData.ofPath(path, mode);
            } else if (pathSetting != null) {
                if (settingBaseDirAsString == null) {
                    throw new PolicyValidationException("files entitlement with a 'path_setting' must specify 'basedir_if_relative'");
                }
                BaseDir baseDir = parseBaseDir(settingBaseDirAsString);
                fileData = FileData.ofPathSetting(pathSetting, baseDir, mode);
            } else {
                throw new AssertionError("File entry validation error");
            }
            filesData.add(fileData.withPlatform(platform).withExclusive(exclusive));

View on GitHub (pinned to db6a809a66)

Solutions

  1. If the path is meant to be absolute, move it into the `path` field and drop `relative_to`.
  2. If the path is meant to be relative, strip the leading separator (and any drive letter on Windows) so it is genuinely relative.

Example fix

// before
{ "relative_path": "/var/log/es", "relative_to": "home", "mode": "read" }

// after (option A: absolute)
{ "path": "/var/log/es", "mode": "read" }
// after (option B: relative)
{ "relative_path": "log/es", "relative_to": "home", "mode": "read" }
Defensive patterns

Strategy: validation

Validate before calling

public static void validateRelativePathIsRelative(String relativePath) {
    if (Path.of(relativePath).isAbsolute()) {
        throw new IllegalArgumentException("relative_path must not be absolute: " + relativePath);
    }
}

Type guard

public static boolean isRelative(String p) {
    return !Path.of(p).isAbsolute();
}

Prevention

When it happens

Trigger: An entry sets `relative_path` to a value that FileUtils.isAbsolutePath reports as absolute on the host OS (leading slash on Unix, drive letter or backslash on Windows).

Common situations: Author copies an absolute path into `relative_path` thinking the field is generic; cross-platform policy where a Windows-style path is treated as absolute; mixing up `path` and `relative_path` semantics; leftover absolute path after refactoring from `path` to `relative_path`.

Related errors


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