{"record":{"id":"40d5c26af2199821","repo":"elastic/elasticsearch","slug":"files-entitlement-with-a-relative-path-must-spec","errorCode":null,"errorMessage":"files entitlement with a 'relative_path' must specify 'relative_to'","messagePattern":"files entitlement with a 'relative_path' must specify 'relative_to'","errorType":"validation","errorClass":"PolicyValidationException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java","lineNumber":278,"sourceCode":"            }\n            Mode mode = parseMode(modeAsString);\n            Platform platform = null;\n            if (platformAsString != null) {\n                platform = parsePlatform(platformAsString);\n            }\n\n            if (relativeTo != null && relativePathAsString == null) {\n                throw new PolicyValidationException(\"'relative_to' may only be used with 'relative_path'\");\n            }\n\n            if (settingBaseDirAsString != null && pathSetting == null) {\n                throw new PolicyValidationException(\"'basedir_if_relative' may only be used with 'path_setting'\");\n            }\n\n            final FileData fileData;\n            if (relativePathAsString != null) {\n                if (relativeTo == null) {\n                    throw new PolicyValidationException(\"files entitlement with a 'relative_path' must specify 'relative_to'\");\n                }\n                BaseDir baseDir = parseBaseDir(relativeTo);\n                Path relativePath = Path.of(relativePathAsString);\n                if (FileUtils.isAbsolutePath(relativePathAsString)) {\n                    throw new PolicyValidationException(\"'relative_path' [\" + relativePathAsString + \"] must be relative\");\n                }\n                fileData = FileData.ofRelativePath(relativePath, baseDir, mode);\n            } else if (pathAsString != null) {\n                Path path = Path.of(pathAsString);\n                if (FileUtils.isAbsolutePath(pathAsString) == false) {\n                    throw new PolicyValidationException(\"'path' [\" + pathAsString + \"] must be absolute\");\n                }\n                fileData = FileData.ofPath(path, mode);\n            } else if (pathSetting != null) {\n                if (settingBaseDirAsString == null) {\n                    throw new PolicyValidationException(\"files entitlement with a 'path_setting' must specify 'basedir_if_relative'\");\n                }\n                BaseDir baseDir = parseBaseDir(settingBaseDirAsString);","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java#L260-L296","documentation":"Thrown when `relative_path` is present on a files-entitlement entry but `relative_to` is missing. A relative path is ambiguous without a base directory to resolve against, so the parser requires the companion `relative_to` field to name the anchor (config/data/home/shared_data/shared_repo).","triggerScenarios":"An entry has `relative_path` but no `relative_to`, e.g. `{ \"relative_path\": \"logs\", \"mode\": \"read\" }`.","commonSituations":"Author assumes a default base dir; forgot the companion field; template missing the line; refactor that renamed or removed `relative_to`.","solutions":["Add `\"relative_to\": \"<base>\"` where <base> is one of config, data, home (or shared_data/shared_repo for internal modules).","If you actually meant an absolute path, switch to `path` instead of `relative_path`."],"exampleFix":"// before\n{ \"relative_path\": \"logs\", \"mode\": \"read\" }\n\n// after\n{ \"relative_path\": \"logs\", \"relative_to\": \"home\", \"mode\": \"read\" }","handlingStrategy":"validation","validationCode":"public static void validateRelativePathPairing(Map<String,Object> entry) {\n    if (entry.containsKey(\"relative_path\") && !entry.containsKey(\"relative_to\")) {\n        throw new IllegalArgumentException(\"relative_path requires relative_to\");\n    }\n}","typeGuard":"public static boolean relativePathOk(Map<String,Object> e) {\n    return !e.containsKey(\"relative_path\") || e.containsKey(\"relative_to\");\n}","tryCatchPattern":null,"preventionTips":["Always emit relative_to alongside relative_path.","If you meant an absolute path, switch to the `path` field instead.","Enforce the pairing via a JSON Schema if/then rule."],"tags":["entitlements","files","policy","validation","paths"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}