elastic/elasticsearch · error · IllegalStateException
Invalid module name in policy: layer [%s] does not have modu
Error message
Invalid module name in policy: layer [%s] does not have module [%s]; available modules [%s]; policy path [%s]
What it means
Thrown by PolicyUtils.validatePolicyScopes while cross-checking a parsed policy's scopes against the set of module names known to belong to the layer. Every scope's moduleName must appear in moduleNames; otherwise the policy references a module the layer does not own and cannot enforce.
Source
Thrown at libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyUtils.java:134
);
}
} catch (Exception e) {
throw new IllegalStateException("Unable to parse policy patch for layer [" + layerName + "]", e);
}
}
return null;
}
static VersionedPolicy decodeEncodedPolicy(String base64String, String layerName, boolean isExternalPlugin) throws IOException {
byte[] policyDefinition = Base64.getDecoder().decode(base64String);
return new PolicyParser(new ByteArrayInputStream(policyDefinition), layerName, isExternalPlugin).parseVersionedPolicy();
}
private static void validatePolicyScopes(String layerName, Policy policy, Set<String> moduleNames, String policyLocation) {
// TODO: should this check actually be part of the parser?
for (Scope scope : policy.scopes()) {
if (moduleNames.contains(scope.moduleName()) == false) {
throw new IllegalStateException(
Strings.format(
"Invalid module name in policy: layer [%s] does not have module [%s]; available modules [%s]; policy path [%s]",
layerName,
scope.moduleName(),
String.join(", ", moduleNames),
policyLocation
)
);
}
}
}
public static Policy parsePolicyIfExists(String pluginName, Path pluginRoot, boolean isExternalPlugin) throws IOException {
Path policyFile = pluginRoot.resolve(POLICY_FILE_NAME);
if (Files.exists(policyFile)) {
try (var inputStream = Files.newInputStream(policyFile, StandardOpenOption.READ)) {
return new PolicyParser(inputStream, pluginName, isExternalPlugin).parsePolicy();
}View on GitHub (pinned to db6a809a66)
Solutions
- Read the message: it lists the offending module, the available modules, and the policy path.
- Fix the scope's `module` field to match one of the listed available modules.
- If the module was renamed, update the policy file to use the new name.
- If you genuinely need to scope another module, the policy must be supplied by that module's layer, not yours.
Example fix
// before
{
"module": "old-module-name",
"entitlements": { ... }
}
// after
{
"module": "renamed-module",
"entitlements": { ... }
} Defensive patterns
Strategy: validation
Validate before calling
public static void validateScopesAgainstModules(Policy policy, Set<String> moduleNames) {
for (Scope s : policy.scopes()) {
if (!moduleNames.contains(s.moduleName())) {
throw new IllegalStateException("Scope module " + s.moduleName()
+ " not in available modules " + moduleNames);
}
}
} Prevention
- Generate policy files from the same manifest that declares module names so they cannot drift.
- Run validatePolicyScopes in a build-time check before packaging a plugin.
- When renaming a module, grep policy files for the old name in the same PR.
When it happens
Trigger: An encoded policy patch lists a scope whose `module` field names a module that is not in the moduleNames set passed to parseEncodedPolicyIfExists. Common when a plugin declares scopes for a sibling module it does not contain.
Common situations: Typos in the module name in a policy file; renaming a module without updating its policy patch; copy-pasting a policy from one plugin into another whose module set differs; third-party plugin trying to grant entitlements to a core module it does not own.
Related errors
- Unable to parse policy patch for layer [{}]
- Not a valid module {} for {}
- entitlement class [{}] has more than one constructor annotat
- entitlement class [{}] has non-static method annotated with
- entitlement class [{}] has more than one constructor and/or
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/c3963fb731bbc4c8.
Report an issue: GitHub.