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
- Replace mutation with construction: Tuples.pair(e.getKey(), newValue)
- If in-place mutation is genuinely required, build entries with new AbstractMap.SimpleEntry<>(k, v), which supports setValue
- 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
- Never call setValue on entries you did not construct - assume foreign Map.Entry objects are immutable
- When you need mutation, copy into new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue()) at the boundary
- Keep a lint/grep pass for '.setValue(' in code that handles Map.Entry from public APIs
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
- Wrong key length. Required ${options.getBitLength()}, but go
- Key ${name} does not exist in ${this}
- Problem removing ${versionName} from ${this}
- Problem removing ${name} from ${this}
- Can't store key ${versionName} in ${this}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/b9ba0aa3c9d1810e.
Report an issue: GitHub.