Runtime Error 28: Out of stack space (Recursive loops gone wrong).

Excel displays Runtime Error 28: Out of stack space when VBA exhausts its allotted call stack memory. This almost always results from runaway recursion—a procedure calling itself repeatedly without hitting a termination condition—or an accidental loop between worksheet events triggering each other indefinitely.

Quick Answer

Resolve Runtime Error 28 by disabling worksheet event listening (Application.EnableEvents = False) inside Worksheet_Change macros to stop infinite event loops, and verify that recursive functions have a verified base-case exit condition (If ... Then Exit Function) that runs before the stack limit is exceeded.


Understanding the Call Stack

Every time a procedure or function is called, VBA places a return address, local variables, and execution parameters onto a special memory structure called the call stack. When the procedure finishes (End Sub or End Function), that frame is removed from the stack, freeing the memory.

If a procedure calls another procedure (or calls itself) continuously without returning, stack frames accumulate. VBA allocates a finite amount of stack space. Once that limit is reached, it throws Runtime Error 28 and terminates.


The Two Most Common Culprits

1. Uncontrolled Event Loops (Worksheet_Change)

The single most frequent trigger in Excel development is writing to a worksheet inside a Worksheet_Change event without disabling events:

' DANGEROUS: Causes Runtime Error 28
Private Sub Worksheet_Change(ByVal Target As Range)
    ' This write triggers Worksheet_Change AGAIN,
    ' which writes again, which triggers it again...
    Target.Offset(0, 1).Value = Target.Value * 2
End Sub

Each write to Target.Offset fires the event again before the initial execution finishes. Within milliseconds, hundreds of nested calls fill the stack.

The Solution: Always toggle Application.EnableEvents:

Private Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo CleanExit

    ' Disable events to prevent recursive firing
    Application.EnableEvents = False

    If Not Intersect(Target, Range("A:A")) Is Nothing Then
        Target.Offset(0, 1).Value = Target.Value * 2
    End If

CleanExit:
    ' Always re-enable events
    Application.EnableEvents = True
End Sub

For deeper mechanics on handling Excel event loops safely, consult Events Debugging: Why EnableEvents = False is necessary to prevent infinite loops..

2. Recursive Functions Missing an Exit Condition

Recursive routines (functions that call themselves to traverse file directories, hierarchies, or BOM structures) require an explicit base case:

' BROKEN: No base case to stop recursion
Function Factorial(n As Long) As Long
    Factorial = n * Factorial(n - 1) ' Calls itself infinitely into negative numbers
End Function

' FIXED: Base case terminates recursion
Function FactorialSafe(n As Long) As Long
    If n <= 1 Then
        FactorialSafe = 1
    Else
        FactorialSafe = n * FactorialSafe(n - 1)
    End If
End Function

If your macro handles recursive logic across large lists or parent-child records, also check Org Chart Data: Troubleshooting “Self-Referencing” parent-child IDs in HR hierarchy files..