Learning Objectives
By the end of this lesson you will be able to:
- Explain the "end before start" bug class and how it manifests
- Identify the symptoms: negative duration, empty result sets, and silent acceptance
- Detect inversion bugs in forms, APIs, and SQL queries
- Explain why some systems silently swap start and end dates
- Design test cases specifically targeting date order inversion
What Is an Inversion Bug?
An inversion bug occurs when a system accepts a date range where the end date is earlier than the start date, then either processes it incorrectly or fails silently. For example:
- Check-in: 2025-07-15
- Check-out: 2025-07-10
This is logically nonsensical — the guest would be checking out before checking in. But if the system does not validate the order of the two dates, it will proceed with this invalid state, leading to unpredictable downstream behavior.
How Inversion Manifests
Inversion bugs surface in several distinct ways depending on where they propagate:
Negative duration: The system calculates the number of nights as end - start, which yields -5 in the example above. If this is used to calculate a price, the result may be a negative charge, a credit to the customer's account, or an arithmetic exception.
Empty result set: In SQL, a query like WHERE event_date BETWEEN '2025-07-15' AND '2025-07-10' returns zero rows on most databases. The system may interpret this as "no conflicts found" and allow the booking — creating an invisible phantom reservation.
Silent acceptance: Some systems simply store the inverted range without error. The problem only surfaces when a report or export reveals that end < start in the data, or when a downstream calculation breaks.
Application crash: If the system computes a duration and passes it to a function that expects a positive number (e.g., date range iteration), it may throw an exception or enter an infinite loop.
Detecting Inversion in Different Layers
In forms: Submit a date range where end < start and observe the response. The UI should display a validation error before submission. If it does not, note it but also proceed to test the API directly.
In APIs: Send a JSON or form payload with an inverted range directly to the server endpoint. The server must reject it with an appropriate HTTP 4xx error and a clear message. If it returns 200 and a success response, the bug is confirmed.
In SQL: Examine the WHERE clause in the relevant query. If the clause is BETWEEN :start AND :end without a prior check that start ≤ end, the query is vulnerable to returning empty results for inverted ranges, which may be silently interpreted as "no conflict".
Why Systems Silently Swap Start and End
Some date pickers automatically swap start and end when the user selects an end date before the start date. This is a usability feature — the picker assumes the user made a mistake and corrects it. However, it creates a problem: the system never exposes the user's actual input to validation. If the API is called directly with an inverted range, the API layer does not perform the same correction, and the bug is exposed.
Additionally, some backend developers, knowing that users sometimes confuse start and end, add a silent swap: if (end < start) { swap(start, end); }. This "defensive" code hides the bug from unit tests but means the system accepts inverted input from any client that bypasses the UI.
Test Cases for Inversion
| TC# | Start | End | Expected result |
|---|---|---|---|
| TC01 | 2025-07-10 | 2025-07-15 | Accept (valid) |
| TC02 | 2025-07-10 | 2025-07-10 | Accept or reject (per system rules for zero-duration) |
| TC03 | 2025-07-15 | 2025-07-10 | Reject with clear error |
| TC04 | 2025-07-15 | 2025-07-14 | Reject with clear error |
| TC05 | 9999-12-31 | 2025-01-01 | Reject with clear error (extreme inversion) |
TC03 and TC04 are the primary inversion detection cases. Send them via the API, not just the UI.
Summary
Inversion bugs are subtle because many systems suppress the symptom rather than fixing the root cause: date pickers swap automatically, backend code swaps silently, and SQL BETWEEN returns an empty set instead of an error. A thorough tester sends inverted date ranges directly to the server API and verifies that the response is an explicit rejection with a meaningful error message — not a silent success, an empty result, or a crash.