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

  1. Verify the field/setter is whitelisted and settable for the runtime receiver class.
  2. Doc/_source fields are generally read-only in scripts; use ctx or params for mutable maps instead.
  3. Type the receiver concretely to surface the missing setter at compile time.
  4. 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

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


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