---
title: "Error handling — Opening Hours for Laravel | Roundly"
description: "Every package exception extends one base class — catch them together, or handle stale writes and oversized queries on their own."
url: https://roundly-consulting.com/open-source/docs/opening-hours-for-laravel/error-handling
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Opening Hours for Laravel](https://roundly-consulting.com/open-source/docs/opening-hours-for-laravel.md)

# Error handling

All exceptions extend the abstract OpeningHoursException (a RuntimeException), so you can catch everything in one place. Messages are developer-facing English; user-facing text travels as translated violation messages:

```php
use RoundlyConsulting\OpeningHours\Exceptions\OpeningHoursException;
use RoundlyConsulting\OpeningHours\Exceptions\QueryRangeTooLargeException;

try {
    $days = $hours->forPeriod('2026-01-01', '2027-12-31');
} catch (QueryRangeTooLargeException $e) {
    // $e->requestedDays, $e->maxDays — split the range or raise max_query_days
} catch (OpeningHoursException $e) {
    // every package exception extends this RuntimeException
}
```

| Exception | Thrown when |
| --- | --- |
| `InvalidOpeningHoursException` | A definition fails validation; violations() returns every problem. |
| `InvalidTimeException / InvalidDateException` | A malformed time, range, date or month-day. |
| `InvalidTimezoneException` | A timezone that is not an IANA name. |
| `QueryRangeTooLargeException` | A span — or one booking with its buffers — beyond max\_query\_days (requestedDays, maxDays). |
| `StaleOpeningHoursException` | A concurrent write moved the revision (expected, actual). |
| `CalendarNotFoundException` | An exception write targets a calendar the owner doesn’t have (never synced, or soft-deleted) — sync() it first. |
| `InvalidBusyPeriodException / TooManyBusyPeriodsException` | An empty or inverted busy period, an invalid weight or column, or more periods than limits.busy\_periods. |
| `InvalidSlotQueryException` | A slot query without a duration or with an out-of-range setting. |
| `InvalidOwnerException` | The owner is not persisted, doesn’t implement OpeningHoursOwner, or can’t be found. |
| `OutsideMaterializedHorizonException` | An SQL scope instant outside the materialized horizon. |

Invalid config values surface as the toolkit’s InvalidConfigurationException.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/opening-hours-for-laravel.md)
