---
title: "Exceptions — Approvals for Laravel | Roundly"
description: "One ApprovalsException base class and eight specific exceptions — what triggers each and how to catch them."
url: https://roundly-consulting.com/open-source/docs/approvals-for-laravel/exceptions
language: en
---

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

[Approvals for Laravel](https://roundly-consulting.com/open-source/docs/approvals-for-laravel.md)

# Exceptions

Every package exception lives in RoundlyConsulting\\Approvals\\Exceptions and extends ApprovalsException, itself a RuntimeException — one catch covers the whole family:

| Exception | Thrown when |
| --- | --- |
| `ClosedApprovalRequestException` | A decision or withdrawal — approve, reject, toggle, ask or cancel — reaches a closed request (approved, rejected, cancelled or expired), pinned with within() even while a later round is open, or because all the subject’s requests are closed (for). Its $request property is that request. |
| `IncompletePendingApprovalException` | A builder decides without an actor (missingActor) or an approvable (missingApprovable). |
| `InvalidApprovalModelException` | A configured model class doesn’t extend the expected base model (forClass). |
| `InvalidApprovalRequestException` | A decision — toggle() included — or close() is pinned to another subject’s request (foreignSubject); a request builder gets both from() and stages() (mixedApprovers); workflow() follows from(), rule(), any(), quorum(), weighted(), stages() or continueOnRejection(), which the preset defines (definedByWorkflow); ask() follows weight() (weightOnAsk); reject() follows an expiry (expiryOnReject); cancel() follows weight() or an expiry (settingsOnCancel); close() follows because() (reasonOnClose), or as(), weight() or an expiry (settingsOnClose); an approver is unsaved (unsavedApprover); a request needs more approvals than it names (moreRequiredThanNamed); a quorum is below 1 (thresholdBelowOne) or out of the approvers’ reach (unreachableThreshold); a request or stage its rule could never approve because it needs no approvals — e.g. an unnamed request under the default Unanimous rule (needsNoApprovals). |
| `InvalidDelegationException` | Self-delegation (selfDelegation), a window that ends before it starts (endsBeforeStart), or ApprovalDelegation::revoke($at) with a moment in the future (futureRevocation). |
| `InvalidStatusTransitionException` | An illegal status transition on the Approval model (between), or close() with an outcome other than Cancelled or Expired — even when no round is open (notAClosingOutcome). |
| `UnauthorizedApprovalException` | The authorization gate denies the actor (forActor), or the actor is not a named approver of the request or its open stage, nor a delegate of one (notAnApprover). |
| `UnknownWorkflowException` | A workflow preset is missing (named) or malformed (invalid). |

```php
use RoundlyConsulting\Approvals\Exceptions\ApprovalsException;
use RoundlyConsulting\Approvals\Exceptions\ClosedApprovalRequestException;
use RoundlyConsulting\Approvals\Exceptions\UnauthorizedApprovalException;
use RoundlyConsulting\Approvals\Facades\Approvals;

try {
    Approvals::for($post)->as($user)->approve();
} catch (UnauthorizedApprovalException $e) {
    // the gate denied this actor, or the request does not name it
} catch (ClosedApprovalRequestException $e) {
    // the round is over — $e->request is the closed request
} catch (ApprovalsException $e) {
    // any other approvals error
}
```

Each exception is built by the named static factory shown in brackets above, which is handy when you assert messages in tests.

## 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/approvals-for-laravel.md)
