elastic/elasticsearch · error · UnsupportedOperationException

${className} does not support putAll()

Error message

${className} does not support putAll()

What it means

LazyPropertyMap overrides Map.putAll(Map) to throw UnsupportedOperationException even though put() and remove() are supported. putAll accepts a plain Map<K,V> which cannot carry the per-entry Supplier or PropertyNormalization metadata that single-entry put(K, Supplier<V>, PropertyNormalization) supports; allowing it would silently degrade entries to eager/default-normalized values. Iterate and put() individually instead.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/LazyPropertyMap.java:101

    public V put(K key, Supplier<V> supplier) {
        return put(key, supplier, PropertyNormalization.DEFAULT);
    }

    public V put(K key, Supplier<V> supplier, PropertyNormalization normalization) {
        assertNotNull(supplier, "supplier for key '" + key + "'");
        PropertyMapEntry<K, V> previous = delegate.put(key, new PropertyMapEntry<>(key, supplier, normalization));
        return previous == null ? null : previous.getValue();
    }

    @Override
    public V remove(Object key) {
        PropertyMapEntry<K, V> previous = delegate.remove(key);
        return previous == null ? null : previous.getValue();
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        throw new UnsupportedOperationException(this.getClass().getName() + " does not support putAll()");
    }

    @Override
    public void clear() {
        delegate.clear();
    }

    @Override
    public Set<K> keySet() {
        return delegate.keySet();
    }

    @Override
    public Collection<V> values() {
        return delegate.values().stream().peek(this::validate).map(PropertyMapEntry::getValue).collect(Collectors.toList());
    }

    @Override

View on GitHub (pinned to db6a809a66)

Solutions

  1. Replace putAll(m) with m.forEach((k, v) -> lazyMap.put(k, v)).
  2. If the source map already has Supplier values, use the put(K, Supplier<V>) overload per entry.
  3. Restructure so defaults are applied before constructing the LazyPropertyMap, not merged after.

Example fix

// before
lazyMap.putAll(defaults); // UnsupportedOperationException
// after
defaults.forEach((k, v) -> lazyMap.put(k, v));
Defensive patterns

Strategy: validation

Validate before calling

if (map instanceof LazyPropertyMap) {
    throw new IllegalStateException("putAll() not supported on LazyPropertyMap; use forEach+put");
}

Type guard

static boolean isLazyPropertyMap(Map<?,?> m) { return m instanceof LazyPropertyMap; }

Prevention

When it happens

Trigger: Calling .putAll(someMap) on a LazyPropertyMap. Common when constructing config maps from existing Map literals, merging two maps, or using collectors like Collectors.toMap that feed into putAll.

Common situations: Migrating `map.putAll(defaults)` from a LinkedHashMap to LazyPropertyMap; Gradle plugin code that merges user config with defaults in bulk; builder patterns that accumulate via putAll.

Related errors


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