# range-unsatisfiable

The **bounds** of a read or an observation **leave no event** that could match.

- **Routes:** `read-events` and `observe-events`
- **Description:**
    - when the lower bound lies above the upper bound: `range is unsatisfiable: lowerBound lies above upperBound`
    - when `upperBound` is exclusive at `0`: `range is unsatisfiable: an exclusive upperBound at 0 leaves nothing to read`
    - when `lowerBound` is exclusive at the largest possible event ID: `range is unsatisfiable: an exclusive lowerBound at the largest event ID leaves nothing to read`
    - when the event that `fromLatestEvent` starts at lies above `upperBound`: `range is unsatisfiable: fromLatestEvent starts above upperBound`
- **Details:** None; `details` is an empty object.

## Why It Happens

Before it reads anything, EventSourcingDB turns the **[bounds](/learn/tutorials/first-steps-with-eventsourcingdb/reading-events#reading-a-specific-range)** into the first and the last event ID to read: an **exclusive `lowerBound`** starts one ID after its own, an **exclusive `upperBound`** ends one ID before its own. If the first ID then lies **above the last**, no event can match, and the read is refused. This happens with **swapped bounds**, for example, or with two exclusive bounds next to each other, such as an exclusive `lowerBound` at `23` and an exclusive `upperBound` at `24`.

With **`fromLatestEvent`**, a read starts at the latest event of the given type in the given subject, which EventSourcingDB looks up once the bounds have passed. If that event lies above `upperBound`, the read is refused as well. Observing has no `upperBound`, so there, only an exclusive `lowerBound` at the largest possible event ID is refused.

A range that is possible but holds no events, such as one beyond the latest event, is not an error: the read simply ends with its `end` item. A `lowerBound` together with `fromLatestEvent` is reported as **[`selection-conflicting`](/docs/eventsourcingdb/errors/selection-conflicting)**, before the range is checked.

## How to Fix It

Choose bounds that leave at least one event ID between them, keeping in mind that an exclusive bound leaves out the ID it names. Sending the same request again fails the same way: the bounds alone decide, and the latest event that `fromLatestEvent` starts at only moves further up as events are written, so raise `upperBound` or leave it out.

## Example

To read the events of `/books/42` with a `lowerBound` that is exclusive at `23` and an `upperBound` that is exclusive at `24`, EventSourcingDB answers with this error, as a line of the stream, and then ends the stream with its `end` item:

```json
{
  "type": "error",
  "data": {
    "code": "https://docs.eventsourcingdb.io/errors/range-unsatisfiable",
    "description": "range is unsatisfiable: lowerBound lies above upperBound",
    "details": {}
  }
}
```
