← Documentation homeValues for the named bounds (BPS, MAX_PERFORMANCE_FEE_BPS, MAX_CORRELATED_SENIOR_LEVERAGE_BPS, etc.) live in the Constants table on the metavault page. This page describes the errors themselves; the cap values are not repeated here so the two sources can't drift.
| Error | When it fires |
|---|
InvalidAmount() | A numeric input is zero (zero deposit, zero shares, zero notice). |
InvalidAddress() | Required address argument is address(0) (constructor vault, receiver, etc.). |
InvalidRate() | A premium-rate argument exceeds BPS, is below minProtectionPremiumBps, or an immutable premium floor argument exceeds BPS. |
InvalidFeeRate() | A performance-fee-rate argument exceeds MAX_PERFORMANCE_FEE_BPS. |
InsufficientAssetReceived(uint256 expected, uint256 received) | transferFrom delivered less than asked; fee-on-transfer or rebasing assets are unsupported. |
| Error | When it fires |
|---|
DepositsPaused() | Either depositSenior or depositJunior while depositsPaused is true. Single global flag; there is no senior-only pause mode. |
| Error | When it fires |
|---|
ProtectionTooThin(uint256 seniorAssets, uint256 juniorAssets, uint256 requiredJuniorAssets) | A senior deposit (or junior withdrawal) would push senior NAV past the senior-leverage cap (MAX_CORRELATED_SENIOR_LEVERAGE_BPS). |
InsufficientJuniorProtection(uint256 requestedAssets, uint256 maxAssets) | A junior withdrawal would breach the senior protection floor (i.e. exceed maxJuniorWithdrawAssets). |
InsufficientVaultLiquidity(uint256 requestedAssets, uint256 availableAssets) | The wrapped ERC4626 cannot satisfy the requested redemption right now (gates closed, queue full, etc., transient). |
TrancheWiped(uint8 trancheId) | New deposits into a tranche whose NAV has reached zero while shares are still outstanding. The wiped side is terminal until a new series is deployed; new capital cannot resurrect the zero unit price. |
Symmetric for senior and junior, indexed by holder address.
| Error | When it fires |
|---|
WithdrawalNoticePending(uint256 executableAt) | withdrawSenior / withdrawJunior called before the notice has matured. |
WithdrawalNoticeTooSmall(uint256 requestedShares, uint256 noticedShares) | Execution requested more shares than the notice covers. |
WithdrawalNoticeExpired() | Execution attempted with no active notice on file. |
WithdrawalNoticeStale(uint256 staleAt) | Execution attempted after executableAt + NOTICE_EXECUTION_WINDOW; the holder must cancel or the stale senior notice must be cleared. |
WithdrawalNoticeNotStale(uint256 staleAt) | clearStaleSeniorWithdrawal called before the senior notice's execution window elapsed. |
WithdrawalNoticeActive() | requestSeniorWithdrawal / requestJuniorWithdrawal called while the holder already has an active notice in that tranche. |
| Error | When it fires |
|---|
KeeperReceiverMustBeOwner() | A non-owner caller tried to execute another holder's matured notice and send proceeds to an address other than the holder. |
KeeperNotAuthorized() | keeperRestricted is true and a non-PROTOCOL_ROLE caller tried to execute another holder's matured notice. Holder self-execution is always allowed. |
These guard the boundary between the metavault and the wrapped ERC4626. They should not fire against a well-behaved 4626; they exist to detect non-conforming integrations. The factory's asset allowlist, Morpho V2 provenance check, and gate-weld check are the deploy-time guardrails; these errors are the runtime backstop.
| Error | When it fires |
|---|
InvalidUnderlyingWithdrawal(uint256 expectedShares, uint256 burnedShares) | The underlying vault burned a different number of shares than the metavault expected during a redemption. |
UnderlyingValueLoss(uint256 minAssets, uint256 actualAssets) | The underlying vault delivered fewer assets than the minimum the metavault computed (modulo one unit of rounding). Approved underlyings are expected to be no-fee/no-slippage, so this catches misbehaving integrations before the loss is socialised across tranches. |
| Error | When it fires |
|---|
AccessControlUnauthorizedAccount(address account, bytes32 neededRole) | Caller lacks the role gating a privileged setter. OPERATOR_ROLE gates setProtectionPremiumRate + setDepositsPaused; PROTOCOL_ROLE gates setPerformanceFeeRate, setFeeRecipient, and setKeeperRestricted. Inherited from OpenZeppelin's AccessControl. |
Need the 4-byte selector for a revert? Compute bytes4(keccak256(errorSig)). The reference frontend's decodeContractError helper does this lookup automatically.