apache/hadoop · error · UnsupportedOperationException

Tuple is immutable

Error message

Tuple is immutable

What it means

Tuples.pair(k, v) returns a private immutable Tuple implementing Map.Entry: both fields are final and setValue always throws UnsupportedOperationException. Tuples are value objects - 'changing' one means constructing a new pair, not mutating the old one.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/functional/Tuples.java:79

    private Tuple(final K key, final V value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public K getKey() {
      return key;
    }

    @Override
    public V getValue() {
      return value;
    }

    @Override
    public V setValue(final V value) {
      throw new UnsupportedOperationException("Tuple is immutable");
    }

    @Override
    public String toString() {
      return "(" + key + ", " + value + ')';
    }

    @Override
    public boolean equals(final Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      Tuple<?, ?> tuple = (Tuple<?, ?>) o;
      return Objects.equals(key, tuple.key) && Objects.equals(value, tuple.value);
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Replace mutation with construction: Tuples.pair(e.getKey(), newValue)
  2. If in-place mutation is genuinely required, build entries with new AbstractMap.SimpleEntry<>(k, v), which supports setValue
  3. Audit shared Map.Entry utilities for setValue calls before feeding them tuples

Example fix

// before
for (Map.Entry<String,Integer> e : tuples) {
  e.setValue(e.getValue() + 1); // UnsupportedOperationException: Tuple is immutable
}

// after: build new tuples
List<Map.Entry<String,Integer>> out = new ArrayList<>();
for (Map.Entry<String,Integer> e : tuples) {
  out.add(Tuples.pair(e.getKey(), e.getValue() + 1));
}
// or, when mutation is required:
Map.Entry<String,Integer> mutable = new AbstractMap.SimpleEntry<>(k, v);
Defensive patterns

Strategy: fallback

Type guard

static boolean isImmutableHadoopTuple(Object o) {
  // Tuple is private; identify by name before attempting any Map.Entry mutation
  return o != null && "org.apache.hadoop.util.functional.Tuples$Tuple".equals(o.getClass().getName());
}

Prevention

When it happens

Trigger: Calling entry.setValue(v) on anything returned by Tuples.pair(); passing tuples to generic Map.Entry utilities that remap values in place (entry-stream transforms, merge loops, mutation of List<Map.Entry>); swapping a mutable Pair implementation for Tuples in existing code.

Common situations: Refactors away from mutable entry types (AbstractMap.SimpleEntry, a custom Pair with setters); generic library code that accepts Map.Entry and mutates it; in-place update loops ported from code that used a mutable pair.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/b9ba0aa3c9d1810e. Report an issue: GitHub.