Infinite recursion in JavaScript quicksort?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Infinite recursion in JavaScript quicksort happens when the partitioning step fails to reduce the problem size — typically because the pivot element is not excluded from the recursive calls, or because all elements end up in one partition. The fix is to ensure the pivot is placed at its final position and excluded from both recursive calls, and that the base case (if (arr.length <= 1) return arr) is correctly handled. The most common bug is including the pivot in the left or right subarray, which means the array size never shrinks and the recursion never terminates.
The Buggy Implementation
The problem: left includes pivot (because 3 <= 3 is true), so left is [3, 1, 2] — the same array. The recursion never reduces the input size.
The Fix: Exclude the Pivot
Or more cleanly, use slice to separate the pivot:
Another Bug: Wrong Comparison Operator
Fix: use <= for left and > for right (or < and >=):
In-Place Quicksort (Lomuto Partition)
The functional-style filter approach creates new arrays. An in-place version is more memory efficient but has its own recursion pitfalls:
The key: pivotIndex - 1 and pivotIndex + 1 ensure the pivot is excluded from both recursive calls.
Hoare Partition (Classic)
With Hoare partitioning, the recursive calls use (low, p) and (p + 1, high) — not (low, p - 1) and (p + 1, high) like Lomuto. Using wrong bounds with Hoare causes infinite recursion.
Preventing Stack Overflow with Large Arrays
JavaScript has limited call stack size. For very large arrays, add tail-call optimization manually:
This limits the recursion depth to O(log n) regardless of input.
Common Pitfalls
- Including the pivot in the
leftorrightpartition: This is the primary cause of infinite recursion. If the pivot is inleft(viax <= pivotwithout excluding index 0) and no elements go toright, theleftarray is the same size as the input, causing infinite recursion. Always exclude the pivot from both subarrays. - Wrong bounds in Hoare vs Lomuto partition: Hoare partition returns an index where
arr[j]may not be the pivot, so the recursive call uses(low, p)and(p+1, high). Using Lomuto-style(low, p-1)with Hoare partition skips elements and causes incorrect sorting or infinite loops. - Choosing first/last element as pivot on sorted input: Picking
arr[0]orarr[high]as pivot on already-sorted data causes O(n^2) behavior and deep recursion (potentially stack overflow). Use median-of-three or random pivot selection for robustness. - Off-by-one in the base case: Using
if (arr.length < 1)instead ofif (arr.length <= 1)means single-element arrays are still processed, which does not cause infinite recursion but wastes computation. For in-place versions,if (low >= high)is the correct stopping condition. - Mutating the array during filter: Using
arr.splice()or modifyingarrwhile filtering creates unpredictable behavior. The functional approach should usearr.slice(1)to create a new array excluding the pivot, leaving the original array unchanged.
Summary
- Infinite recursion occurs when the pivot is not excluded from recursive calls, keeping the subarray the same size
- Use
arr.slice(1)to separate the pivot, then filter the rest intoleftandright - For in-place quicksort, use
pivotIndex - 1andpivotIndex + 1as bounds (Lomuto) orpandp + 1(Hoare) - Choose median-of-three or random pivots to avoid worst-case O(n^2) on sorted input
- Optimize tail recursion by iterating on the larger partition to limit stack depth to O(log n)
Related reading
- Infinite Recursion with Jackson JSON and Hibernate JPA issue
- Infix to postfix algorithm that takes care of unary operators
- Infomap community detection understanding
- Inlining Algorithm
- Initial state in React with Redux not working
- input typenumber/ is not showing a number keypad on iOS
- INFO warnings about multiple modules in Spring Boot, what do they mean?
- Info.plist Utility Error Info.plist couldn't be opened because there is no such file

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.