apache/beam · error · IllegalArgumentException

TupleTag ${tag} corresponds to a non-singleton result

Error message

TupleTag ${tag} corresponds to a non-singleton result

What it means

getOnly() asserts the requested tag maps to exactly one value for the key. If more than one element exists in the iterable for that tag, the result is non-singleton and the method refuses to silently pick one.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/CoGbkResult.java:409

  private @Nullable <V> V innerGetOnly(
      TupleTag<V> tag, @Nullable V defaultValue, boolean useDefault) {
    int index = schema.getIndex(tag);
    if (index < 0) {
      throw new IllegalArgumentException("TupleTag " + tag + " is not in the schema");
    }
    @SuppressWarnings("unchecked")
    Iterator<V> unions = (Iterator<V>) valueMap.get(index).iterator();
    if (!unions.hasNext()) {
      if (useDefault) {
        return defaultValue;
      } else {
        throw new IllegalArgumentException(
            "TupleTag " + tag + " corresponds to an empty result, and no default was provided");
      }
    }
    V value = unions.next();
    if (unions.hasNext()) {
      throw new IllegalArgumentException(
          "TupleTag " + tag + " corresponds to a non-singleton result");
    }
    return value;
  }

  /**
   * A re-iterable that notifies an observer at every advance, and upon finishing, but only once
   * across all copies.
   *
   * @param <T> The value type of the underlying iterable.
   */
  private static class ObservingReiterator<T> implements Reiterator<T> {

    public interface Observer<T> {
      /**
       * Called exactly once, across all copies before advancing this iterator.
       *
       * <p>The iterator rather than the element is given so that the callee can perform a copy if

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use get(tag) to obtain an Iterable and iterate all values
  2. Ensure the PCollection for that tag is deduplicated per key (e.g. Distinct or combine) before joining
  3. Use getAll(tag) when multiple values are legitimate

Example fix

// before
V v = result.getOnly(tag); // throws if multiple
// after
for (V v : result.getAll(tag)) { /* handle each */ }
Defensive patterns

Strategy: validation

Validate before calling

if (result.getAll(tag).iterator().hasNext() && result.getAll(tag).spliterator().getExactSizeIfKnown() != 1) { /* handle multi-value */ }

Try / catch

try { return result.getOnly(tag); } catch (IllegalArgumentException e) { /* fall back to iterable handling */ }

Prevention

When it happens

Trigger: Calling getOnly(tag) on a key where the corresponding PCollection produced multiple records for that key in the CoGroupByKey output.

Common situations: Using getOnly() on many-to-many join results; one side of the join emits multiple values per key (e.g. repeated events per user id).

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/6f3d6e493f3512c5. Report an issue: GitHub.