---
title: "Exceptions — Credits for Laravel | Roundly"
description: "The credits exceptions and the money-for-laravel exceptions the package lets through — what throws them and what they carry."
url: https://roundly-consulting.com/open-source/docs/credits-for-laravel/exceptions
language: en
---

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

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

# Exceptions

Credits throws two exceptions of its own under a common base, passes a handful of money-for-laravel exceptions through unwrapped, throws package-toolkit’s InvalidConfigurationException on a malformed setting, and lets Laravel’s DeadlockException reach you inside your own transactions:

| Exception | Thrown when |
| --- | --- |
| `CreditsException` | Base class (a RuntimeException) of InsufficientCreditsException and BucketNotDenominatedException — catch it to handle any credits failure. |
| `InsufficientCreditsException` | A deduction would take a bucket below minimum\_balance while overdraft is disallowed. Carries $creditable, $requested (signed), $available (the raw balance) and $minimum (the floor the guard enforced, so $available - $minimum is what could be spent); message from credits::messages.insufficient, or credits::messages.insufficient\_above\_minimum when the floor is not 0. |
| `BucketNotDenominatedException` | A money-typed call — the scope’s money(), addMoney(), deductMoney(), modifyMoney() or formatMoney(), or the trait’s creditsBalanceMoney(), modifyCreditsMoney() or formatCreditsBalance() — on a bucket not listed in credits.currencies. Carries $bucket (the resolved name); message from credits::messages.not\_denominated. |
| `InvalidArgumentException` | add() or deduct() (or addMoney() / deductMoney()) received a negative amount — use modify() for a signed change. |
| `CurrencyMismatch` | From money: modifyCreditsMoney() received a Money in another currency (code + exponent). |
| `AmountOverflow` | From money: a value does not fit the signed 64-bit ledger — a Money amount, the bucket balance a change would produce or a setTo() delta (nothing is written), or a total across buckets or a past balance being read. |
| `UnknownCurrency` | From money: credits.currencies maps a bucket to a code the registry does not know. |
| `InvalidMoneyConfiguration` | From money: credits.currencies is malformed, or credits.rounding names no rounding mode. |
| `InvalidAmount` | From money: a display scale beyond 36 decimal places. |
| `InvalidConfigurationException` | From package-toolkit: a config value is malformed — a model that is not Credit or a subclass, an unknown key\_type or primary\_key\_type, a non-boolean allow\_overdraft, a non-integer minimum\_balance, a non-string default\_bucket, a scale outside 0–36, or a non-callable modifiable entry. The message names the key. |
| `DeadlockException` | From Laravel: inside your own DB::transaction() on Postgres REPEATABLE READ or SERIALIZABLE, a racing change of the same owner (SQLSTATE 40001). Nothing is written — retry the whole transaction. |

## Handling them

Catch the specific cases you can act on, then fall back to the base class:

```php
use RoundlyConsulting\Credits\Exceptions\CreditsException;
use RoundlyConsulting\Credits\Facades\Credits;
use RoundlyConsulting\Credits\Exceptions\InsufficientCreditsException;
use RoundlyConsulting\Money\Exceptions\AmountOverflow;
use RoundlyConsulting\Money\Exceptions\CurrencyMismatch;

try {
    Credits::for($user)->bucket('store_credit')->modifyMoney($amount, 'checkout');
} catch (InsufficientCreditsException $e) {
    // not enough in the bucket: $e->requested, $e->available, $e->minimum, $e->creditable
} catch (CurrencyMismatch | AmountOverflow $e) {
    // wrong currency, or beyond the 64-bit ledger — nothing was written
} catch (CreditsException $e) {
    // any other credits failure, e.g. BucketNotDenominatedException ($e->bucket)
}
```

A refused change never leaves a partial write: the overdraft guard and the 64-bit bound run inside the write’s transaction before the row is appended, and the money checks run before it starts.

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