google/guava · error · AssertionFailedError
Should not call merge function if key was mapped to null
Error message
Should not call merge function if key was mapped to null
What it means
Thrown inside the remapping function of MapMergeTester.testMappedToNull. Per the Map.merge contract, when the key is present but mapped to null, the function MUST NOT be invoked; merge should treat null as 'no value' and insert the new value. This firing means your Map calls the function for a null-mapped key.
Source
Thrown at android/guava-testlib/src/com/google/common/collect/testing/testers/MapMergeTester.java:76
throw new AssertionFailedError(
"Should not call merge function if key was absent");
}));
expectAdded(e3());
}
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
@CollectionSize.Require(absent = ZERO)
public void testMappedToNull() {
initMapWithNullValue();
assertEquals(
"Map.merge(keyMappedToNull, value, function) should return value",
v3(),
getMap()
.merge(
getKeyForNullValue(),
v3(),
(oldV, newV) -> {
throw new AssertionFailedError(
"Should not call merge function if key was mapped to null");
}));
expectReplacement(entry(getKeyForNullValue(), v3()));
}
@MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_KEYS})
public void testMergeAbsentNullKey() {
assertEquals(
"Map.merge(null, value, function) should return value",
v3(),
getMap()
.merge(
null,
v3(),
(oldV, newV) -> {
throw new AssertionFailedError(
"Should not call merge function if key was absent");
}));View on GitHub (pinned to 94f39958ba)
Solutions
- Treat a present-but-null value exactly like an absent mapping in merge: do not call the function, just store the new value.
- Mirror HashMap.merge semantics: oldValue == null (whether absent or explicitly null) -> store value without invoking the function.
- Ensure the ALLOWS_NULL_VALUES path is exercised in your own unit tests.
Example fix
// before
V old = containsKey(k) ? get(k) : DEFAULT;
V merged = f.apply(old, v); // BUG: called when get(k)==null
// after
V old = get(k);
if (old == null) { put(k, v); return v; } // null value treated as absent
V merged = f.apply(old, v);
if (merged == null) remove(k); else put(k, merged);
return merged; Defensive patterns
Strategy: validation
Validate before calling
// Ensure null-mapped value is treated as absent.
Map<K,V> m = newMap();
m.put(k, null);
m.merge(k, v, (o,n) -> { throw new AssertionFailedError("f must not be called for null value"); });
assertEquals(v, m.get(k)); Prevention
- In merge(), treat get(k)==null the same whether the key is absent or explicitly mapped to null.
- Test the ALLOWS_NULL_VALUES merge path explicitly in your own suite.
When it happens
Trigger: Running MapTestSuiteBuilder (with ALLOWS_NULL_VALUES, size != ZERO) against your Map; testMappedToNull initializes a null value and calls merge. Your implementation calls the BiFunction instead of treating null as absent.
Common situations: A merge() that distinguishes 'contains key' from 'value non-null' incorrectly, calling apply() whenever containsKey(k) regardless of the stored null; Map implementations wrapping null values in a sentinel.
Related errors
- Should not call merge function if value was null
- Should not call merge function if key was absent
- Call using() before createTestSuite().
- Call named() before createTestSuite().
- Call withFeatures() before createTestSuite().
AI-assisted analysis of google/guava@94f39958ba (2026-08-13).
Data as JSON: /api/errors/9c5090af3997ca82.
Report an issue: GitHub.