fullstackhero/dotnet-starter-kit · error · InvalidOperationException
Insufficient wallet balance.
Error message
Insufficient wallet balance.
What it means
Wallet.Dbit throws InvalidOperationException when the requested debit amount exceeds the wallet's current balance — i.e. Balance.Subtract(amount) would go negative. The wallet does not support overdrafts.
Solutions
- Check wallet.Balance >= amount before calling Debit, or surface a 'top up required' flow.
- Top up the wallet (Credit) to cover the amount.
- Serialize debits per wallet (row lock / optimistic concurrency) to prevent overdraft races.
- Verify amount units and Money construction so the debit value is correct.
Example fix
// before
wallet.Debit(amount, kind, desc, refId); // throws when balance short
// after
if (wallet.Balance.Amount >= amount.Amount)
{
wallet.Debit(amount, kind, desc, refId);
} Defensive patterns
Strategy: validation
Validate before calling
if (wallet.Balance.Amount < amount.Amount) throw new InsufficientBalanceException(wallet.Balance, amount);
Try / catch
try { wallet.Debit(amount, kind, desc, refId); } catch (InvalidOperationException) { // prompt wallet top-up } Prevention
- Pre-check balance before charging
- Top up wallets proactively based on spend forecasts
- Serialize debits per wallet to avoid overdraft races
- Confirm amount units (cents vs units) when constructing Money
When it happens
Trigger: Debiting an amount greater than Balance; two concurrent debits each valid individually but overdrafting together; debiting before a prior top-up/credit transaction was committed.
Common situations: Charging a customer whose wallet was not topped up; race conditions between parallel charge jobs on the same wallet; currency/amount unit mismatches (cents vs whole units) inflating the debit.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Cannot mark invoice as paid from status
- Paid invoices cannot be voided.
- Operation requires invoice status
- Top-up request must be
- Tenant context is required.
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/676bbf6cfa5f4c2d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Billing/Modules.Billing/Domain/Wallet.cs:55
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(amount.Amount, 0m);
// Validate currency before touching the aggregate: Money.Add throws on a
// mismatch, so computing the new balance first keeps a rejected credit from
// leaving a phantom ledger row behind.
var newBalance = Balance.Add(amount);
var tx = WalletTransaction.Create(Id, TenantId, amount, kind, description, referenceId);
_transactions.Add(tx);
Balance = newBalance;
UpdatedAtUtc = DateTime.UtcNow;
return tx;
}
public WalletTransaction Debit(Money amount, WalletTransactionKind kind, string description, string? referenceId)
{
ArgumentNullException.ThrowIfNull(amount);
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(amount.Amount, 0m);
var remaining = Balance.Subtract(amount);
if (remaining.Amount < 0m)
throw new InvalidOperationException("Insufficient wallet balance.");
var tx = WalletTransaction.Create(Id, TenantId, amount.Multiply(-1m), kind, description, referenceId);
_transactions.Add(tx);
Balance = remaining;
UpdatedAtUtc = DateTime.UtcNow;
return tx;
}
}
View on GitHub (pinned to 3f2959e683)