spring-projects/spring-framework · error · UnsupportedOperationException

Element access not supported - for custom ObjectProvider…

Error message

Element access not supported - for custom ObjectProvider classes, implement stream() to enable all other methods

What it means

UnsupportedOperationException from the default ObjectProvider.stream() at line 237. iterator(), orderedStream(), forEach, and the new Predicate overloads all derive from stream(); a custom ObjectProvider that overrides only getObject() (inherited from ObjectFactory) leaves stream() unimplemented, so any iteration-based call fails.

Solutions

  1. Override stream() in your custom ObjectProvider to return the matching bean instances (e.g. Stream.of(bean)).
  2. Use a real DependencyDescriptor/ContextBeanProvider-backed ObjectProvider instead of a hand-rolled one.
  3. In tests, return Stream.of(...) or Collections.singletonList(bean).stream().

Example fix

// before
public class TestProvider<T> implements ObjectProvider<T> {
    public T getObject() { return bean; } // iterator() -> UnsupportedOperationException
}

// after
@Override public Stream<T> stream() { return Stream.of(bean); }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure stream() is overridden before iterating
Method s = provider.getClass().getMethod("stream");
if (s.isDefault()) {
    throw new UnsupportedOperationException("provider must override stream()");
}

Type guard

static boolean supportsStream(ObjectProvider<?> p) {
    try {
        return !p.getClass().getMethod("stream").isDefault();
    } catch (NoSuchMethodException e) { return false; }
}

Prevention

When it happens

Trigger: Calling iterator()/stream()/orderedStream()/forEach on a minimal ObjectProvider implementation that did not override stream(). The message tells you implementing stream() unlocks all derived element-access methods.

Common situations: Mockito mocks or stub ObjectProviders in tests; legacy ObjectProvider implementations written before Spring 5.1 (when stream() was introduced).

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/6df61f38fd93992c. Report an issue: GitHub.

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java:237

	 */
	@Override
	default Iterator<T> iterator() {
		return stream().iterator();
	}

	/**
	 * Return a sequential {@link Stream} over all matching object instances,
	 * without specific ordering guarantees (but typically in registration order).
	 * <p>Note: The result may be filtered by default according to qualifiers on the
	 * injection point versus target beans and the general autowire candidate status
	 * of matching beans. For custom filtering against type-matching candidates, use
	 * {@link #stream(Predicate)} instead (potentially with {@link #UNFILTERED}).
	 * @since 5.1
	 * @see #iterator()
	 * @see #orderedStream()
	 */
	default Stream<T> stream() {
		throw new UnsupportedOperationException("Element access not supported - " +
				"for custom ObjectProvider classes, implement stream() to enable all other methods");
	}

	/**
	 * Return a sequential {@link Stream} over all matching object instances,
	 * pre-ordered according to the factory's common order comparator.
	 * <p>In a standard Spring application context, this will be ordered
	 * according to {@link org.springframework.core.Ordered} conventions,
	 * and in case of annotation-based configuration also considering the
	 * {@link org.springframework.core.annotation.Order} annotation,
	 * analogous to multi-element injection points of list/array type.
	 * <p>The default method applies an {@link OrderComparator} to the
	 * {@link #stream()} method. You may override this to apply an
	 * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator}
	 * if necessary.
	 * <p>Note: The result may be filtered by default according to qualifiers on the
	 * injection point versus target beans and the general autowire candidate status
	 * of matching beans. For custom filtering against type-matching candidates, use

View on GitHub (pinned to 69bf83ad71)