elastic/elasticsearch · error · UnsupportedOperationException

${className} does not support remove()

Error message

${className} does not support remove()

What it means

LazyPropertyList deliberately overrides List.remove(Object) to throw UnsupportedOperationException. The list stores deferred Supplier entries with per-entry PropertyNormalization metadata; removing by resolved value would force eager evaluation of every lazy supplier and discard normalization info, so the operation is intentionally unsupported rather than silently lossy. Use clear() to reset or remove(int) is NOT supported either via this path.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/LazyPropertyList.java:78

        return delegate.stream().peek(this::validate).map(PropertyListEntry::getValue).toList().toArray(a);
    }

    @Override
    public boolean add(T t) {
        return delegate.add(new PropertyListEntry<>(() -> t, PropertyNormalization.DEFAULT));
    }

    public boolean add(Supplier<T> supplier) {
        return delegate.add(new PropertyListEntry<>(supplier, PropertyNormalization.DEFAULT));
    }

    public boolean add(Supplier<T> supplier, PropertyNormalization normalization) {
        return delegate.add(new PropertyListEntry<>(supplier, normalization));
    }

    @Override
    public boolean remove(Object o) {
        throw new UnsupportedOperationException(this.getClass().getName() + " does not support remove()");
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return delegate.stream().map(PropertyListEntry::getValue).collect(Collectors.toSet()).containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        c.forEach(this::add);
        return true;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        int i = index;
        for (T item : c) {
            this.add(i++, item);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Rebuild the list from scratch instead of removing an element: collect desired entries and clear()+addAll().
  2. If you control the call site, switch to index-based mutation via set(int, T) or add(int, T).
  3. Avoid passing LazyPropertyList to generic collection helpers; copy to a plain ArrayList first if mutation is required.

Example fix

// before
lazyList.remove(unwanted); // UnsupportedOperationException
// after
List<T> kept = new ArrayList<>(lazyList);
kept.remove(unwanted);
lazyList.clear();
kept.forEach(lazyList::add);
Defensive patterns

Strategy: validation

Validate before calling

// Before mutating, check the operation is supported
if (list instanceof LazyPropertyList) {
    throw new IllegalStateException("remove() not supported on LazyPropertyList; rebuild the list instead");
}

Type guard

static boolean isLazyPropertyList(List<?> l) { return l instanceof LazyPropertyList; }

Try / catch

try { list.remove(o); } catch (UnsupportedOperationException e) { /* rebuild list from scratch */ }

Prevention

When it happens

Trigger: Calling .remove(Object) on any LazyPropertyList instance. This commonly happens when passing a LazyPropertyList to generic List-manipulation utilities, collection algorithms, or third-party code that invokes the full List contract.

Common situations: Using libraries that call remove() defensively (e.g., list.removeAll(Collections.singletonList(x))); refactoring a plain ArrayList to LazyPropertyList and discovering mutation methods are gone; Gradle plugin code that mutates lists passed across task boundaries.

Related errors


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