A catalog of recurring errors observed in production curator markets, organized by symptom. Each entry covers the cause and the fix.Documentation Index
Fetch the complete documentation index at: https://kamino.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Reserve-creation errors
InvalidOracleConfig, InvalidScopePriceAccount, InvalidPythPriceAccount, InvalidSwitchboardAccount
Symptom: add-asset-to-market or update-reserve-config reverts with one of these.
Cause: The oracle pubkey in the reserve config’s tokenInfo doesn’t match the account passed to the instruction. The on-chain validator strictly checks that what’s passed matches what’s configured.
Fix: Run get-oracle-mappings to retrieve the canonical oracle addresses for the asset. Update tokenInfo.scopeConfiguration.priceFeed (or the Pyth / Switchboard equivalent) to match. Re-run.
InvalidTwapConfig
Symptom: Reserve creation or oracle update reverts with this error.
Cause: TWAP is enabled (maxTwapDivergenceBps > 0) but either maxAgeTwapSeconds is 0, or the configured oracle source doesn’t expose a TWAP.
Fix: Either disable TWAP (maxTwapDivergenceBps: 0) or ensure the oracle source has a TWAP available and maxAgeTwapSeconds is set to a non-zero value.
Reserve already exists for this mint
Symptom: add-asset-to-market reverts.
Cause: A reserve for this (mint, market) pair already exists. Each market can have at most one reserve per mint.
Fix: Use update-reserve-config for the existing reserve, or deploy a new market if you need a separate reserve for the same mint (e.g., a different fixed-term track).
Withdrawal queue errors
WithdrawTicketValueTooSmall
Symptom: A user calls enqueue-to-withdraw and the transaction reverts.
Cause: The ticket value (the user’s withdrawal amount, valued in USD) is below the market-level min_withdraw_queued_liquidity_value.
Fix: Either lower min_withdraw_queued_liquidity_value on the market config, or have the user enqueue a larger amount. The default value is intended to filter dust; if a real depositor is hitting it, the threshold may be too high.
WithdrawTicketIssuanceDisabled / WithdrawTicketRedemptionDisabled / WithdrawTicketCancellationDisabled
Symptom: A user calls one of enqueue-to-withdraw, withdraw-queued-liquidity, or cancel-withdraw-ticket and gets the corresponding “disabled” error.
Cause: The relevant flag on the market is set to 0.
Fix: Set withdraw_ticket_issuance_enabled, withdraw_ticket_redemption_enabled, or withdraw_ticket_cancellation_enabled to 1 on the market config and re-deploy. See Withdrawal queue.
Redemption returns less than expected
Symptom: A user redeems their ticket but receives a partial amount. Cause: The reserve has only partial liquidity available. The program pays out what it can; the ticket carries the remaining amount and stays in the queue for the next round. Fix: Working as designed. The user re-submitswithdraw-queued-liquidity after additional liquidity becomes available (borrower repayment, new deposit, liquidation).
Repay / withdraw errors
MinNetValueInObligationViolated
Symptom: A borrower partial-repay or partial-withdraw reverts.
Cause: After the operation, the obligation would hold less than min_net_value_in_obligation_sf (default approximately $0.000001). The program rejects operations that would leave dust positions.
Fix: The user must either:
- Repay the full debt (close the position cleanly), or
- Repay enough that the remaining debt is comfortably above the threshold
”Withdraw amount is less than withdrawal penalty”
Symptom: A user attempts a withdrawal and the SDK rejects with this error. Cause: The withdrawal would leave less than the SDK’s penalty floor in available liquidity (sub-cent dust). The SDK guards against creating uneconomical withdrawals. Fix: The user adjusts the withdrawal amount to either fully exit or leave a meaningful balance. UI integrators may treat sub-cent residuals as “absolute zero” and round display values accordingly.Liquidation issues
Sub-$2 obligations not liquidating cleanly
Symptom: A position with very small debt is underwater but liquidators aren’t successfully clearing it. Cause: Belowmin_full_liquidation_value_threshold, the close-factor cap is bypassed and full liquidation is allowed — but liquidator gas economics may not justify clearing a sub-$2 position. Above the threshold, partial liquidations apply, which are uneconomical at this scale.
Fix: Tune min_full_liquidation_value_threshold to a value that aligns with liquidator gas economics on your network. A higher threshold lets more positions be fully liquidated cleanly. Combine with min_value_skip_liquidation_ltv_checks to skip LTV health checks for tiny positions.
Liquidations on a fixed-term reserve don’t fire at maturity
Symptom: A fixed-term position passes itsdebt_maturity_timestamp but isn’t liquidatable.
Cause: Either mature_reserve_debt_liquidation_enabled or obligation_borrow_debt_term_liquidation_enabled is 0 on the market.
Fix: Set both flags to 1 on the market config. See Fixed rate reserves.
Borrow order errors
BorrowOrderAlreadyExists
Symptom: A user calls set-borrow-order and it reverts.
Cause: The obligation already has an open borrow order. The program enforces one open order per obligation.
Fix: Cancel the existing order first. Each obligation can hold one borrow order at a time by deliberate design.
BorrowOrderFillValueTooSmall
Symptom: A lender calls fill-borrow-order and it reverts.
Cause: The fill amount is below min_borrow_order_fill_value.
Fix: Increase the fill size, or lower the market’s threshold if it’s set too high for the asset’s economics.
Vault interaction errors
Vault invest doesn’t create withdrawal tickets
Symptom: A vault manager decreases a reserve’s allocation weight, expecting the program to enqueue tickets. Nothing happens.
Cause: Vault-side automatic ticket creation on invest is currently a user-initiated flow on the underlying klend market. The vault does not auto-enqueue tickets when a manager rebalances.
Fix: End users withdraw via the standard kvault redeem_in_kind → receive cTokens → enqueue ticket flow. Vault-level rebalancing affects target allocation but doesn’t preemptively queue user withdrawals.
CLI errors
Unauthorized on a config update
Symptom: update-reserve-config or update-lending-market-from-config reverts with Unauthorized.
Cause: The signer’s pubkey doesn’t match lending_market_owner.
Fix: Verify ownership with get-market-or-vault-admin-info. If the market was transferred to a multisig, use --mode multisig --multisig <PUBKEY> (every update on a multisig-owned market goes through proposals).
MarketImmutable
Symptom: Any update returns this error.
Cause: immutable: 1 was previously set on the market. No further updates are possible.
Fix: None available. The flag is irreversible. To deploy a fresh configuration, create a new market.
Public RPC rate limits
Symptom: Transactions fail to land, the CLI reports timeouts, simulations fail with rate-limit errors. Cause: TheRPC URL in .env is the public Solana endpoint, which is rate-limited.
Fix: Use a private RPC provider (Helius, Triton, QuickNode, etc.). Public mainnet RPC is for casual use; production curator operations should run against a dedicated endpoint.
Visibility issues
Market doesn’t appear in app.kamino.com
Symptom: The market is on-chain and operational, but doesn’t show up in the public Kamino app.
Cause: The Kamino app filters markets by a curated whitelist (resources.json in the kamino-resources repo). Markets not on the list don’t surface in the public UI.
Fix: If you want the market on the public app, coordinate with the Kamino team to add it. If not, the market is accessible via direct deep-link (?market=<MARKET_ADDRESS>) and via your own UI.
When the page above doesn’t help
If you’re hitting an error that isn’t here:- Check the on-chain state with
download-lending-market-configanddownload-reserve-config— confirm what’s actually configured. - Re-run the failing operation with
--mode inspectand open the simulator — the explorer often gives a more specific reason than the CLI’s surface error. - Cross-reference field names against the Reserve config reference and Market config reference — reserve config JSON uses camelCase; market config JSON uses snake_case (mirrors the on-chain Rust).
- Check the klend repository for the error name in the program’s error list.