The SPL's two families say who must fix the problem. A LogicException means the calling code is wrong; only a code change cures it. A RuntimeException means the world was not as expected (a file, a row, a remote service), so it happens in correct code and callers may recover.
| Class | Family | Throw it when | Bookshop example |
|---|---|---|---|
| InvalidArgumentException | Logic | An argument has the wrong form | A malformed SKU |
| DomainException | Logic | A value breaks a business rule | A discount above 100% |
| UnexpectedValueException | Runtime | Outside data has the wrong shape | A payment reply with no status |
| OutOfBoundsException | Runtime | A key is missing at run time | An order ID with no row |
| OverflowException | Runtime | A container is full | A cart at its line limit |
Built-in functions throw ValueError and TypeError for bad arguments, and typed parameters under strict_types (Strict Types) throw TypeError for you. For user input, throw a validation exception with field-level messages instead (Structured Validation).