Skip to content

How to Resolve Error "CS0163: Control cannot fall through from one case label" in C#

Learn how to fix C# Compiler Error CS0163 by properly terminating switch-case blocks with break, return, or goto case to prevent unintended fall-through behavior.

The Compiler Error CS0163 is a control flow safety error. The message reads: "Control cannot fall through from one case label ('case X:') to another".

In languages like C or C++, if you omit a break statement at the end of a case block, the program automatically executes the code in the next case block. This behavior is called Fall-Through. C# considers implicit fall-through to be a common source of bugs (executing code unintentionally). Therefore, C# forbids falling through from one non-empty case to another. Every case that contains statements must explicitly end with a jump statement.

This guide explains how to properly terminate case blocks and how to achieve fall-through behavior explicitly if needed.

Understanding the "No Fall-Through" Rule

If a case block contains any instructions (even just a variable declaration or a console print), it is considered "non-empty". A non-empty case must end with one of the following keywords:

  • break (Exits the switch)
  • return (Exits the method)
  • throw (Exits via exception)
  • goto case <value> (Jumps to another case)
  • goto default (Jumps to default)

If the compiler detects a path where execution reaches the end of the case block and tries to "fall" into the next one, it raises CS0163.

Scenario 1: The Forgotten Break (Common Mistake)

This is the most frequent cause. A developer writes logic for a case but simply forgets to type break; at the end.

Example of error

public void ProcessLevel(int level)
{
    switch (level)
    {
        case 1:
            Console.WriteLine("Easy Mode");
            // ⛔️ Error CS0163: Control cannot fall through from one case label ('case 1:') to another.
            // Execution hits this line and tries to fall into 'case 2', which is forbidden.
        
        case 2:
            Console.WriteLine("Medium Mode");
            break;
    }
}

Solution: Add Break

Simply add the break; statement.

public void ProcessLevel(int level)
{
    switch (level)
    {
        case 1:
            Console.WriteLine("Easy Mode");
            break; // ✅ Correct: Safely exits the switch

        case 2:
            Console.WriteLine("Medium Mode");
            break;
    }
}

Scenario 2: Incomplete Conditional Paths

If you use if/else statements inside a case, every possible branch must contain a jump statement. If one branch (e.g., the else) allows execution to reach the bottom of the case, the error occurs.

Example of error

public void CheckAdmin(string role, bool isActive)
{
    switch (role)
    {
        case "Admin":
            if (isActive)
            {
                Console.WriteLine("Welcome Admin");
                return; // Exits method (Valid)
            }
            // ⛔️ Error CS0163: What if 'isActive' is false?
            // The code falls out of the 'if' and hits the bottom of 'case "Admin"',
            // trying to fall into 'default'.
        
        default:
            Console.WriteLine("Access Denied");
            break;
    }
}

Solution: Cover All Paths

Ensure the loop or condition has a definitive exit for all scenarios.

public void CheckAdmin(string role, bool isActive)
{
    switch (role)
    {
        case "Admin":
            if (isActive)
            {
                Console.WriteLine("Welcome Admin");
                return;
            }
            else
            {
                Console.WriteLine("Inactive Admin");
                break; // ✅ Correct: The 'else' path now breaks properly
            }
        
        default:
            Console.WriteLine("Access Denied");
            break;
    }
}

Solution 1: Explicit Fall-Through (goto case)

If you actually want the logic to execute Case A and then immediately execute Case B (the behavior of C++ fall-through), you must be explicit using goto case.

public void ProcessPayment(int status)
{
    switch (status)
    {
        case 1: // "Authorized"
            Console.WriteLine("Payment Authorized.");
            // We want to proceed immediately to "Capture" logic (Case 2)
            // ✅ Correct: Explicitly jump to case 2
            goto case 2; 

        case 2: // "Captured"
            Console.WriteLine("Payment Captured.");
            break;
    }
}

Solution 2: Stacked Cases (Empty Cases)

There is one exception to the rule: Empty case labels are allowed to fall through. This allows you to group multiple inputs that should execute the exact same code.

public void CheckDay(string day)
{
    switch (day)
    {
        // ✅ Correct: These cases are empty, so they fall through to "Sunday".
        case "Saturday":
        case "Sunday":
            Console.WriteLine("It's the weekend!");
            break;

        default:
            Console.WriteLine("Work day.");
            break;
    }
}

Conclusion

CS0163 enforces intention. It prevents you from accidentally running code you didn't mean to.

  1. Standard Case: Always end a non-empty case with break; or return;.
  2. Grouping Inputs: Use stacked empty cases (case 1: case 2:) to share logic.
  3. Sharing Logic: If you need to run one case and then another, use goto case <val>;.
Navigation