if / else if chain with no final else

ID

apex.maintainability.missing_final_else

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Control Flow

Language

Apex

Description

Reports an if / else if chain that ends without a final else branch. A trigger-context dispatch chain, which is exhaustive by construction, is not reported.

Rationale

A chain of conditions enumerates the cases the author had in mind; without a final else there is no answer for the case nobody thought of. In Apex that case arrives as a new picklist value, a new record type or a null the query returned, and the chain simply falls through: the variable keeps whatever it had, the method returns null, and the record is saved with a field the code never set. Nothing throws and nothing is logged, so the defect is found by the person who reads the data weeks later, not by the test run.

The following code illustrates the pattern detected by this rule:

public class ShippingRates {

    public static Decimal rate(String country) {
        // FLAGGED: if / else if chain with no final else
        if (country == 'ES') {
            return 4.95;
        } else if (country == 'PT') {
            return 6.50;
        }
        return 0;
    }

    public static String band(Decimal weight) {
        if (weight < 1) {
            return 'light';
        // FLAGGED: if / else if chain with no final else
        } else if (weight < 10) {
            return 'medium';
        } else if (weight < 100) {
            return 'heavy';
        }
        return 'unknown';
    }

    public static String bandWithDefault(Decimal weight) {
        if (weight < 1) {
            return 'light';
        } else if (weight < 10) {
            return 'medium';
        } else {
            return 'heavy';
        }
    }

    public static Boolean isDomestic(String country) {
        if (country == 'ES') {
            return true;
        }
        return false;
    }

    public static String label(Boolean express) {
        if (express) {
            return 'express';
        } else {
            return 'standard';
        }
    }

    public static void dispatch() {
        if (Trigger.isBefore && Trigger.isInsert) {
            AccountTriggerHandler.handleBeforeInsert(Trigger.new);
        } else if (Trigger.isAfter && Trigger.isUpdate) {
            AccountTriggerHandler.handleAfterUpdate(Trigger.new, Trigger.oldMap);
        }
    }
}

Remediation

Close the chain with an else that handles the remaining case explicitly - a default value, an addError on the record, or a thrown exception saying which value was not expected. Where the chain tests a picklist or an enum, a switch on with a when else expresses the same intent and makes the default a required part of the statement.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved