elastic/elasticsearch · error · TestClustersException
Unknown keys in user definition {} for {}
Error message
Unknown keys in user definition {} for {} What it means
Thrown by user(userSpec) when the supplied map contains keys other than 'username', 'password', and 'role'. The node builds an elasticsearch-users useradd invocation from exactly those three keys; any extra key would be ignored silently, so the API rejects it to catch typos and schema drift.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java:743
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
public void user(Map<String, String> userSpec) {
Set<String> keys = new HashSet<>(userSpec.keySet());
keys.remove("username");
keys.remove("password");
keys.remove("role");
if (keys.isEmpty() == false) {
throw new TestClustersException("Unknown keys in user definition " + keys + " for " + this);
}
Map<String, String> cred = new LinkedHashMap<>();
cred.put("useradd", userSpec.getOrDefault("username", "test_user"));
cred.put("-p", userSpec.getOrDefault("password", "x-pack-test-password"));
cred.put("-r", userSpec.getOrDefault("role", "_es_test_root"));
credentials.add(cred);
}
private File getBuildPluginFile(String name) {
URL resource = getClass().getResource(name);
return fileOperations.getResources().getText().fromUri(resource).asFile();
}
@Override
public void rolesFile(File rolesYml) {
roleFiles.add(rolesYml);
}
View on GitHub (pinned to db6a809a66)
Solutions
- Restrict the map to exactly username/password/role.
- Replace 'roles' with 'role', 'pass' with 'password', 'name'/'user' with 'username'.
- If you need multiple roles, pass them comma-separated as the single 'role' value (matches elasticsearch-users -r semantics).
- Filter the map before calling: userSpec.subMap(['username','password','role']).
Example fix
// before: wrong key names user([user: 'alice', pass: 'secret', roles: 'superuser']) // after: correct keys user([username: 'alice', password: 'secret', role: 'superuser'])
Defensive patterns
Strategy: validation
Validate before calling
static final Set<String> USER_KEYS = Set.of("username", "password", "role");
static Map<String,String> sanitizeUser(Map<String,String> in) {
Set<String> extra = new HashSet<>(in.keySet());
extra.removeAll(USER_KEYS);
if (!extra.isEmpty()) {
throw new IllegalArgumentException("Unknown user keys " + extra + "; allowed " + USER_KEYS);
}
return in;
}
// Use: node.user(sanitizeUser(spec)); Type guard
static boolean isValidUserSpec(Map<String,String> in) {
return USER_KEYS.containsAll(in.keySet());
} Prevention
- Use exactly username/password/role keys.
- Map 'roles'->'role', 'pass'->'password', 'name'->'username' when migrating.
- Pass multiple roles as a comma-separated 'role' value.
When it happens
Trigger: Calling node.user([username:'u', password:'p', role:'r', extra:'x']) with a stray key. Common culprits: 'roles' (plural) instead of 'role', 'pass' instead of 'password', 'name' instead of 'username', or test framework boilerplate passing through extra fields.
Common situations: Migrating from an older API that accepted 'roles' plural. Copy-paste from a REST example that uses different field names. Test fixture that forwards an unfiltered map.
Related errors
- extra config file destination can't be relative, was {} for
- supplied keystore file {} does not exist, require for {}
- Can't create extra config file from {} for {} as it does not
- extra jar file {} doesn't appear to be a JAR
- Can't create roles.yml config file from {} for {} as it does
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/e3736386d26dabd7.
Report an issue: GitHub.