Your Code Works. Your Coding Interview Edge Cases Don't.

- Confirmation bias drives engineers to trace their solution with the provided example, not adversarial inputs, because the mental model used to write the code assumes valid input
- Empty and single-element inputs aren't trivial null checks; the real risk is whether your algorithm's invariants hold, not just whether it avoids crashing
- Kadane's algorithm must initialize
max_sumtonums[0], not0, or it returns wrong answers for all-negative arrays - Modulo sign differs by language: Python's
(-13) % 3is2, but Java, C, C++, and Go return-1, causing silent wrong answers in circular indexing or hash functions - The Joshua Bloch overflow bug:
(low + high) / 2corrupted Java's standard binary search for nine years; uselow + (high - low) / 2instead - Say each edge case out loud before declaring done: testing is an explicit scored dimension at Meta and Amazon, and naming what you've checked is documented signal in the write-up
You solved the problem. You walked through your approach, picked the right data structure, wrote clean code, and explained every line as you went. The main example ran correctly. The interviewer nodded.
Then they asked: "What happens if the array is empty?"
Your code threw an index out of bounds exception. You stared at it for three seconds that lasted a decade. You added a check at the top and moved on, but the damage was already in the write-up: "candidate declared done without verifying edge cases."
Coding interview edge cases are one of the most common reasons correct solutions fail. The algorithm is right. The edge case handling is not.
Why Your Brain Defaults to the Happy Path
The cognitive load during a coding interview is real. You're simultaneously understanding the problem, designing an algorithm, translating it to code, narrating your thinking, and watching the clock. By the time you finish writing, your working memory is fully cooked. Research on performance anxiety suggests it can reduce working memory capacity by roughly 30%.
When you mentally trace your code, you use the same mental model you used to write it. That model assumes valid, non-empty, non-degenerate input. So you trace through with the example the interviewer gave you. It works. You say you're done.
This is confirmation bias in a very literal form: you run the cases that confirm your solution, not the ones that expose it. The cases that expose it live at the edges: empty inputs, single elements, all-same values, negatives, overflow, off-by-one boundaries. Every one of those is predictable. None of them require inspiration to find. They just require a habit.

The developer tested every edge case they could think of. Just not the one the user actually tried.
Empty and Single Element Are Not Trivial Null Checks
"Just add a null check." Yes. But the real question is whether your algorithm returns the correct result for these inputs, not just whether it avoids crashing.
An empty array shouldn't just survive. It should return whatever the problem specifies: an empty list, -1, 0, or a documented exception. Single-element inputs are different. Many algorithms implicitly assume at least two elements.
The edge case that kills you is specific to the algorithm's invariants, not just to the input shape. Consider a standard binary search:
def search(nums, target): left, right = 0, len(nums) - 1 while left <= right: mid = left + (right - left) // 2 if nums[mid] == target: return mid elif nums[mid] < target: left = mid + 1 else: right = mid - 1 return -1
Empty input sets right = -1, and left <= right is immediately false. Returns -1. Correct. Single element: left == right == 0, one comparison, done. Also correct.
But rotate that same logic into "search rotated sorted array," and now the invariant for determining which half is sorted breaks precisely when left == right. The empty and single-element cases still pass. A one-element rotated array does not, because the condition nums[left] <= nums[mid] gives no useful information when left == mid.
During clarification, ask directly: can the input be empty? Can there be a single element? Is k guaranteed to be at most n? Stating those constraints out loud is exactly what good clarifying questions signal to the interviewer.
Duplicates Seem Obvious Until Your Guard Condition Is Wrong
The 3Sum problem is a useful case study. Sort the array, fix one element, use two pointers for the rest. Duplicate triplets are the problem. You skip duplicates at the outer index:
for i in range(len(nums) - 2): if i > 0 and nums[i] == nums[i - 1]: continue left, right = i + 1, len(nums) - 1 while left < right: s = nums[i] + nums[left] + nums[right] if s == 0: result.append([nums[i], nums[left], nums[right]]) while left < right and nums[left] == nums[left + 1]: left += 1 while left < right and nums[right] == nums[right - 1]: right -= 1 left += 1 right -= 1 elif s < 0: left += 1 else: right -= 1
The bounds check left < right inside those inner while loops is not optional. Without it, if the remaining elements are all identical (say the input is [0, 0, 0, 0, 0]), you advance left past right and access out-of-bounds memory on the next comparison. This fails only on adversarial inputs. Which is exactly what interviewers reach for when they want to see if you've really thought it through.
Similarly, if you build a frequency map and your code overwrites an existing key, you need to know whether that's correct for the problem. Stating that assumption out loud is signal. Assuming it silently is a gamble.
Negatives Break Assumptions Your Algorithm Made
Kadane's algorithm for Maximum Subarray has a well-known initialization trap. If you initialize max_sum to zero:
def max_subarray(nums): max_sum = 0 # Bug: wrong for all-negative input current = 0 for n in nums: current = max(n, current + n) max_sum = max(max_sum, current) return max_sum
This returns 0 for [-3, -1, -2]. The correct answer is -1. The problem asks for the maximum subarray of a non-empty array, so the empty subarray returning zero is not a valid answer. Zero is not a subarray. You just handed back the result for an input that doesn't exist.
The fix is to initialize to nums[0]:
def max_subarray(nums): max_sum = nums[0] current = nums[0] for n in nums[1:]: current = max(n, current + n) max_sum = max(max_sum, current) return max_sum
Initializing to zero is only correct if the problem allows returning an empty subarray sum. The problem statement determines which version is right. If you never ask about whether all-negative input is possible, you'll use the wrong initialization about half the time.
There's another trap with negatives and modulo. The sign of a % b when a is negative differs by language. In Python, (-13) % 3 evaluates to 2. In Java, C, C++, and Go, it evaluates to -1. JavaScript matches the C behavior. If you write Python but think in Java semantics (or the reverse), any circular index or hash function using modulo will silently produce wrong answers for negative inputs. Java 8 added Math.floorMod() to get the Python-style behavior when you need it.
The Overflow Bug That Fooled Java for Nine Years
In 2006, Joshua Bloch published a post on the Google Research Blog revealing that java.util.Arrays.binarySearch had contained a bug since 1997. The bug was on this line:
int mid = (low + high) / 2;
When low and high are both large positive integers, their sum overflows a signed 32-bit integer and wraps to a negative number. The computed midpoint becomes meaningless. The search breaks.
The fix is one substitution:
int mid = low + (high - low) / 2;
Or with an unsigned right shift that avoids the signed overflow entirely:
int mid = (low + high) >>> 1;
The same bug appeared in Jon Bentley's Programming Pearls, a book written specifically about producing correct programs. It survived formal proof. It survived code review. It lurked for nearly a decade because nobody ran a binary search on an array with 2^30 elements. In the 1980s, an array of one billion elements was inconceivable. By the early 2000s, Google's infrastructure was routine with them. The bug didn't change. The world caught up to it.
Python integers are arbitrary precision, so this particular failure mode does not apply. In Java, C, and C++, it is a real risk whenever your algorithm adds two indices or accumulates a sum that could approach INT_MAX. Mentioning overflow in an interview, and using the safe formula when you spot the risk, is a concise way to show that your thinking extends beyond the happy path.
If you want to go deeper on the off-by-one layer of binary search specifically, the full invariant analysis is in Binary Search: One Invariant to Rule the Search Space.
Six Coding Interview Edge Cases to Test Before You Declare Done
Six categories. After you finish writing, name each one and say how your code handles it. You don't need to trace all six in full. The goal is to say the words before the interviewer has to ask.
Empty input. What does your function return when the array has zero elements, the string is empty, or the graph has no nodes? Does it crash, return a sentinel, or handle correctly?
Single element. What happens with exactly one element? Two-pointer solutions often assume at least two. Linked list solutions often assume head.next is not null. Reversal, cycle detection, merge: all have single-node edge cases.
All-same values. Does your duplicate-skipping logic handle [2, 2, 2, 2]? Does your sliding window handle "aaaa"? Does your majority element algorithm handle an array where every element is the same?
Negatives. Can the input contain negative numbers? Does your initialization assume non-negative? Does your modulo or division assume positive operands?
Overflow. Are you summing two large indices? Multiplying values that could exceed the 32-bit signed range? In Java or C++, name the overflow risk and use the safe formula. In Python, you can skip this one.
Boundary and off-by-one. Are your loop conditions < or <=? Are your binary search bounds inclusive or exclusive? Is your base case correct for the smallest valid input, not just the example?

Declaring done after testing the happy path is exactly this. The interviewer is the product manager here.
Say each one out loud. I know, saying "what if the array is empty?" in front of a stranger feels slightly paranoid. But that stranger is waiting for it. It's a scoring category. Naming the edge cases you've considered gives the interviewer documented signal, and testing is an explicit scoring dimension at Meta and Amazon. Candidates who declare done without it leave that box empty, which shows up in the write-up exactly as you don't want it to.
The checklist is easy to run at a desk. It is genuinely hard to remember when you have eight minutes left and your working memory is gone. Running it on SpaceComplexity during a full voice-based mock interview, where the clock is real and the interviewer is waiting, builds the habit in the conditions that matter.
For a deeper look at how bugs surface mid-interview and how to trace through them systematically, Debugging in a Coding Interview covers the trace-table method and the one-fix-at-a-time rule.