alibaba/nacos · warning · IllegalArgumentException

expected one element but was: <{}>

Error message

expected one element but was: <{}>

What it means

Thrown by CollectionUtils.getOnlyElement(Iterable) when the iterable is non-null and contains more than one element. The message is built by buildExceptionMessage and lists up to 5 of the offending elements followed by '...' if there are more. It enforces a single-element contract.

Source

Thrown at common/src/main/java/com/alibaba/nacos/common/utils/CollectionUtils.java:316

    
    /**
     * return the first element, if the iterator contains multiple elements, will throw {@code
     * IllegalArgumentException}.
     *
     * @throws NoSuchElementException   if the iterator is empty
     * @throws IllegalArgumentException if the iterator contains multiple elements. The state of the iterator is
     *                                  unspecified.
     */
    public static <T> T getOnlyElement(Iterable<T> iterable) {
        if (iterable == null) {
            throw new IllegalArgumentException("iterable cannot be null.");
        }
        Iterator<T> iterator = iterable.iterator();
        T first = iterator.next();
        if (!iterator.hasNext()) {
            return first;
        }
        throw new IllegalArgumentException(buildExceptionMessage(iterator, first));
    }
    
    private static <T> String buildExceptionMessage(Iterator<T> iterator, T first) {
        StringBuilder msg = new StringBuilder();
        msg.append("expected one element but was: <");
        msg.append(first);
        for (int i = 0; i < 4 && iterator.hasNext(); i++) {
            msg.append(", ");
            msg.append(iterator.next());
        }
        if (iterator.hasNext()) {
            msg.append(", ...");
        }
        msg.append('>');
        return msg.toString();
    }
    
    /**

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Tighten the upstream query/filter so it yields exactly one element.
  2. If multiple results are valid, use iterable.iterator().next() or pick by a deterministic tie-breaker instead of getOnlyElement.
  3. Log the element list from the exception message to see what duplicates exist.

Example fix

// before
T only = CollectionUtils.getOnlyElement(results);

// after
if (results.size() == 1) {
    T only = results.iterator().next();
} else {
    // handle ambiguity explicitly
    throw new AmbiguousResultException(results);
}
Defensive patterns

Strategy: validation

Validate before calling

if (iterable == null) return null;
int size = (iterable instanceof Collection) ? ((Collection<?>) iterable).size() : -1;
if (size == 1) {
    return ((Collection<T>) iterable).iterator().next();
}
// size != 1 -> do not call getOnlyElement
return null; // or throw a domain-specific exception

Try / catch

try {
    return CollectionUtils.getOnlyElement(iterable);
} catch (IllegalArgumentException e) {
    // more than one element — e.getMessage() lists them
    throw new AmbiguousResultException(e.getMessage());
}

Prevention

When it happens

Trigger: Calling getOnlyElement on a collection that legitimately has 2+ elements when the caller assumed uniqueness — e.g., a query expected to match one record but matched several.

Common situations: A lookup/filter that should return exactly one result but the filter is too loose (duplicate config keys, multiple instances matching, ambiguous mapping).

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/868a0c98693974a4. Report an issue: GitHub.