elastic/elasticsearch · error · IllegalArgumentException
dynamic setter [receiverClass, name] not found
Error message
dynamic setter [receiverClass, name] not found
What it means
Def.lookupSetter terminal fallback: after Map and List special cases, if no whitelisted field or setX() method matches the name on the receiver class, it throws 'dynamic setter [type, name] not found'. This is the assignment counterpart to the getter-not-found error.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java:714
// special case: maps, and lists
if (Map.class.isAssignableFrom(receiverClass)) {
// maps allow access like mymap.key
// wire 'key' as a parameter, its a constant in painless
return MethodHandles.insertArguments(MAP_PUT, 1, name);
} else if (List.class.isAssignableFrom(receiverClass)) {
// lists allow access like mylist.0
// wire '0' (index) as a parameter, its a constant. this also avoids
// parsing the same integer millions of times!
try {
int index = Integer.parseInt(name);
return MethodHandles.insertArguments(LIST_SET, 1, index);
} catch (final NumberFormatException exception) {
throw new IllegalArgumentException("Illegal list shortcut value [" + name + "].");
}
}
throw new IllegalArgumentException("dynamic setter [" + typeToCanonicalTypeName(receiverClass) + ", " + name + "] not found");
}
/**
* Returns a method handle to normalize the index into an array. This is what makes lists and arrays stored in {@code def} support
* negative offsets.
* @param receiverClass Class of the array to store the value in
* @return a MethodHandle that accepts the receiver as first argument, the index as second argument, and returns the normalized index
* to use with array loads and array stores
*/
static MethodHandle lookupIndexNormalize(Class<?> receiverClass) {
if (receiverClass.isArray()) {
return ArrayIndexNormalizeHelper.arrayIndexNormalizer(receiverClass);
} else if (Map.class.isAssignableFrom(receiverClass)) {
// noop so that mymap[key] doesn't do funny things with negative keys
return MAP_INDEX_NORMALIZE;
} else if (List.class.isAssignableFrom(receiverClass)) {
return LIST_INDEX_NORMALIZE;
}View on GitHub (pinned to db6a809a66)
Solutions
- Verify the field/setter is whitelisted and settable for the runtime receiver class.
- Doc/_source fields are generally read-only in scripts; use ctx or params for mutable maps instead.
- Type the receiver concretely to surface the missing setter at compile time.
- Check for typos and read-only semantics.
Example fix
// before doc['price'].value = 10; // doc fields are read-only // after ctx._source.price = 10;
Defensive patterns
Strategy: type-guard
Type guard
// For update-by-query, write to ctx._source (a Map); never to doc fields or scalars. // Type mutable accumulators as List/Map explicitly.
Try / catch
// On 'dynamic setter [..., name] not found', tell the author the field is read-only or absent; suggest ctx._source or a params Map.
Prevention
- Use ctx._source for source mutations; doc fields are read-only.
- Static-type receivers to surface missing setters at compile time.
- Avoid assigning to immutable wrappers.
When it happens
Trigger: A Painless script writes x.someField = value on a 'def' receiver whose runtime class has no whitelisted settable field or setter method for 'someField'. Examples: assigning to a read-only field, a non-existent property, or a private field.
Common situations: Trying to mutate an immutable wrapper (e.g. a String or boxed primitive). Setting a doc field directly (not allowed — docs are read-only in most contexts). Property name typo. Receiver resolved to a type without a setter.
Related errors
- Illegal list shortcut value [name].
- dynamic method [{}, {}/{}] not found
- Illegal list shortcut value [{}].
- dynamic getter [{}, {}] not found
- Attempting to address a non-array-like type [receiverClass]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/7e3f3bef99a8a44a.
Report an issue: GitHub.