# How to Break Out of a Kotlin forEach Loop: Complete Guide with Examples

> Learn how to break out of a Kotlin forEach loop using labeled returns or traditional for loops. Discover efficient ways to control loop execution in your Kotlin code.

- Repository: [JetBrains/kotlin](https://github.com/jetbrains/kotlin)
- Tags: how-to-guide
- Published: 2026-02-21

---

**Use a labeled return (`return@forEach`) to exit a `forEach` lambda early, or switch to a traditional `for` loop if you need a true `break` statement.**

Kotlin’s `forEach` extension function provides a concise way to iterate over collections, but its lambda-based design prevents the use of traditional `break` statements. According to the JetBrains/kotlin repository source code, understanding how `forEach` is implemented reveals why alternative approaches are necessary.

## Why You Can't Use a Traditional Break Inside forEach

The `forEach` function is defined as an **inline** extension on `Iterable<T>` in [`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt) at lines 1914-1916:

```kotlin
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

```

Because `forEach` accepts a **lambda** (`action: (T) -> Unit`), a traditional `break` statement cannot be used inside that lambda. The Kotlin compiler treats `break` as an attempt to break from the lambda itself, not from the surrounding iteration (which does not exist as a loop construct inside the lambda).

## Method 1: Using a Labeled Return to Exit forEach Early

The most idiomatic way to stop processing elements is using a **labeled return** (`return@forEach`). This performs a non-local return from the lambda, effectively skipping the remaining elements without exiting the enclosing function.

```kotlin
val numbers = listOf(1, 2, 3, 4, 5)

numbers.forEach { n ->
    if (n == 3) return@forEach   // exit the lambda early; continue with next element
    println(n)                    // prints 1, 2, then skips 3, prints 4, 5
}

```

The label `@forEach` tells the compiler to return only from the lambda, not from the surrounding function. This is the equivalent of a `continue` statement in a traditional loop.

## Method 2: Returning from the Enclosing Function

If you need to abort the entire surrounding function (not just skip remaining elements), you can use an **unlabeled** `return` inside the lambda. This works because `forEach` is declared as an **inline** function.

```kotlin
fun findFirstEven(numbers: List<Int>): Int? {
    numbers.forEach {
        if (it % 2 == 0) return it   // returns from `findFirstEven`, not just the lambda
    }
    return null
}

```

When the compiler inlines the `forEach` call, the `return` statement becomes a direct return from `findFirstEven`. This pattern is useful for search operations where you want to exit immediately upon finding a match.

## Method 3: Using a Traditional for Loop with Break

When you need true `break` semantics (exiting the loop completely rather than just returning from a lambda), replace `forEach` with a traditional `for` loop:

```kotlin
val items = (1..10).toList()

for (i in items) {
    if (i == 6) break      // true loop-level break
    print("$i ")           // prints 1 2 3 4 5
}
println()

```

A classic `for` loop provides native `break` and `continue` semantics without requiring labeled returns or inline function considerations. This approach is preferable when you need complex control flow, multiple break conditions, or nested loops.

## Performance and Compilation Considerations

The `forEach` function is marked as `inline`, meaning the compiler copies the function body (including your lambda) directly into the call site. This eliminates the overhead of creating a function object for the lambda, making `forEach` performance-equivalent to a manual `for` loop in most cases.

However, because the lambda is inlined, non-local returns (both labeled and unlabeled) are compiled as direct jumps rather than exception-based stack unwinding. This makes early exit from `forEach` highly efficient compared to similar patterns in non-inline higher-order functions.

## Summary

- **Traditional `break` does not work** inside `forEach` lambdas because `forEach` is not a loop construct but a higher-order function.
- **Use `return@forEach`** to skip the remaining elements and continue execution after the `forEach` block (equivalent to `continue`).
- **Use unlabeled `return`** inside `forEach` to exit the enclosing function entirely, leveraging the `inline` nature of `forEach`.
- **Use a traditional `for` loop** when you need true `break` semantics or complex control flow without labeled returns.

## Frequently Asked Questions

### Can you use break inside a Kotlin forEach?

No, you cannot use a traditional `break` statement inside a `forEach` lambda. The `forEach` function accepts a lambda parameter, and `break` is only valid within loop constructs like `for`, `while`, or `do-while`. Attempting to use `break` inside `forEach` results in a compilation error because the compiler cannot determine which loop to break from.

### What is the difference between return and return@forEach?

`return@forEach` performs a **local return** from the lambda, causing `forEach` to proceed to the next element (similar to `continue` in a regular loop). An unlabeled `return` inside `forEach` performs a **non-local return** from the enclosing function because `forEach` is an inline function. The unlabeled `return` exits the entire surrounding function immediately, not just the lambda.

### Is forEach inlined by the compiler?

Yes, `forEach` is declared as an `inline` function in the Kotlin standard library. The implementation in [`_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/_Collections.kt) shows the `inline` modifier, which causes the compiler to copy the function body and the lambda directly into the call site. This inlining eliminates the runtime overhead of creating a function object for the lambda and enables non-local returns to work efficiently.

### When should I use a for loop instead of forEach?

Use a traditional `for` loop instead of `forEach` when you need **true `break` or `continue` semantics**, when working with **nested loops** where labeled returns become confusing, or when you need to **modify the loop variable** or index during iteration. `for` loops provide clearer control flow for complex iteration patterns, while `forEach` is best suited for simple, side-effect-only operations on each element.