[Java][S6104] False Negative: Does not detect `return null;` in block lambda for computeIfAbsent/com

What language is this for?

Java

Which rule?

  • Rule Key: java:S6104
  • Rule Name: “computeIfPresent” and “computeIfAbsent” should not return null

Why do you believe it’s a false-negative?

The rule is intended to detect cases where computeIfAbsent() or computeIfPresent() is called with a mapping function that returns null. According to the Java Map API, returning null from the BiFunction causes the mapping to be removed, which is usually not the developer’s intention and can lead to subtle bugs.

The current implementation only detects the expression-lambda form:

map.computeIfAbsent(key, k -> null);

It completely misses the far more common block-lambda patterns:

  • k → { return null; }

  • k → { if (…) return null; … }

  • k → { doSomething(); return null; }

These block cases have exactly the same runtime behavior (mapping is removed) but are not reported at all.
How can we reproduce the problem?

Here is a self-contained, fully compilable Java 8+ snippet:

Java

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        // ❌ These three cases are NOT detected (False Negative)
        map.computeIfAbsent("key1", k -> {
            return null;                    // should raise java:S6104
        });

        map.computeIfPresent("key2", (k, v) -> {
            if (v.isEmpty()) {
                return null;                // should raise java:S6104
            }
            return v;
        });

        map.computeIfAbsent("key3", k -> {
            System.out.println("Computing...");
            return null;                    // should raise java:S6104
        });

        // ✅ Only this expression-lambda case is currently detected
        map.computeIfAbsent("key4", k -> null);
    }
}

Expected behavior: All three block-lambda cases should raise java:S6104.

Additional technical detail (for the development team):
The root cause is in NullReturnedOnComputeIfPresentOrAbsentCheck.java:

Java

if (body.is(Tree.Kind.NULL_LITERAL)) {   // ← only this is checked
    // No handling for Tree.Kind.BLOCK + ReturnStatementTree
}

I searched the community forum and GitHub (sonar-java / sonarqube) before posting — no existing issue for this false negative.

Thank you for your help!

I agree with examples key1, key3 and key4 but not key2. The key2 example returns null only conditionally, which seems valid and does not agree with the word “always” in the rule description.

Hi!

Thank you for the report! We appreciate the reproducer that you provided.

You are correct; this is a false positive. I have filed a ticket, SONARJAVA-6373, to track resolution of this issue.