SonarQube fails to detect NullPointerException

Hi

SonarQube Community Edition does not detect potential NullPointerException when a method parameter object is dereferenced without prior null validation, even though the code clearly shows the parameter is never checked for null before calling its methods.

Environment:

SonarQube Version: Enterprise Edition - v2025.1.3
Language: Java
Scanner: sonar-maven-plugin:jar:4.0.0.4121

Expected Behavior:
SonarQube should raise a “NullPointerException might be thrown” issue when updateDto.getShippingAddress() is called without validating that updateDto is not null.

Actual Behavior:
No warning or code smell is detected for the potential NullPointerException on lines where updateDto.getShippingAddress() is invoked.

Code Example:
See the sample code above. The method validateOrderUpdate accepts OrderUpdateDto updateDto as a parameter but never validates if it’s null before calling updateDto.getShippingAddress()

public class OrderValidator {

private static final String ORDER_TYPE_STANDARD = "STD";
private static final String ORDER_TYPE_EXPRESS = "EXP";



public static void validateOrderUpdate(Order existingOrder, OrderUpdateDto updateDto, 

                                       String customerId, List<ValidationError> errorList) {

    

    // Null check for existingOrder

    if (existingOrder.getShippingAddress() == null) {

        return;

    }



    // Potential NullPointerException - updateDto is NOT checked for null

    if (!StringUtils.equals(existingOrder.getOrderType(), ORDER_TYPE_EXPRESS) 

        && !StringUtils.equals(existingOrder.getShippingAddress(), updateDto.getShippingAddress())) {

        errorList.add(new ValidationError("ERR105", "Shipping address mismatch"));

        return;

    }



    // Same issue - updateDto.getShippingAddress() called without null check on updateDto

    if (StringUtils.equals(existingOrder.getOrderType(), ORDER_TYPE_EXPRESS)

        && (StringUtils.equals(customerId, existingOrder.getCustomerId()) 

            || StringUtils.equals(customerId, existingOrder.getTransferredToCustomerId()))

        && !StringUtils.equals(existingOrder.getShippingAddress(), updateDto.getShippingAddress())

    ) {

        errorList.add(new ValidationError("ERR105", "Shipping address mismatch for express order"));

    }

}


}

Hi @ckonca ,

Thanks for reporting this concern.

I noticed a small discrepancy in your post: you initially mention SonarQube Community Edition but later state you’re using Enterprise Edition - v2025.1.3 in the Environment section. Could you please clarify which edition you’re actually using?

Regarding the behavior you’re observing, this is actually working as designed to minimize false positives. By default, our rule does not assume that method parameters are nullable unless there’s explicit evidence suggesting they might be:

  • The parameter is annotated with @Nullable (or similar nullable annotations)

  • The parameter is explicitly checked for null within the method

  • The calling context passes potentially null values

This design choice is intentional because in most codebases, parameters are expected to be non-null by contract, and reporting on every unchecked parameter would generate excessive noise.

A clarifying question: Is validateOrderUpdate a public API or external endpoint? If this method is part of your public API surface and you want to enforce null-safety at the boundary, I’d recommend:

  1. Adding a @Nullable annotation to the updateDto parameter if it can legitimately be null

  2. Adding an explicit null check at the method entry point

  3. Using @NonNull / @Nonnull annotations to document your contract if null values should never be passed

Would either of these approaches work for your use case?