Troubleshooting
Minting
TX stuck in "pending" status
Symptom: A BitGo mint transaction stays in "pending" for more than 10 minutes.
Diagnosis:
- Check the
MINTING_TX_SYNCcron job -- is it running? Any errors? - Check BitGo Express logs -- is the Express container healthy?
- Check the TX on BitGo web console -- what status does BitGo report?
Resolution:
- If BitGo shows the TX as confirmed, the sync cron will pick it up on the next run.
- If BitGo shows an error, the TX may need to be retried.
- If BitGo Express is down, restart the container.
TRANSFER_FROM_FAILED
Symptom: Mint transaction reverts with TRANSFER_FROM_FAILED.
Cause: The minting wallet does not have sufficient token balance or the contract does not have approval.
Resolution:
- Check the wallet's token balance on-chain.
- Check if the minting contract has approval to transfer from the wallet.
- If balance is insufficient, fund the wallet first.
Wallet-mint not reflecting in dashboard
Symptom: A wallet-mint (Safe/EOA) was submitted but does not appear in the TX history.
Cause: Wallet-mints are not synced by MINTING_TX_SYNC (that cron only handles source='bitgo'). The record is created at submission time via POST /api/operations/minting/wallet-mint.
Resolution:
- If the Safe TX is still pending signatures, it has not been submitted on-chain yet. Wait for threshold.
- If the API call to
wallet-mintfailed, the TX may be on-chain but not recorded. Manually check the wallet's TX history on the block explorer.
Oracle
Stale prices (not updating)
Symptom: Oracle prices have not updated in more than 15 minutes.
Diagnosis:
- Check
ORACLE_PRICE_UPDATEcron job for errors. - Common error:
timeout of 30000ms exceeded-- Belo API is slow or down. - Check if the oracle updater wallet (
0xef31...) has enough ETH for gas.
Resolution:
- If Belo API is down, wait for recovery. Prices will update on the next successful run.
- If the wallet is out of gas, send ETH to the oracle updater address.
- If BitGo Express is unreachable, restart the Express container.
Deviation too high between oracle and pool price
Symptom: The Uniswap pool price deviates significantly from the oracle price (shown in dashboard cards).
Cause: Large trades shifted the pool price, or the oracle has not updated recently.
Resolution:
- If oracle is stale, check the cron job (see above).
- If the pool price moved due to a large trade, the
UNISWAP_AUTO_REBALANCEcron should trigger a rebalance if deviation exceedsrebalanceTriggerPercent. - For immediate action, run a manual rebalance from the Uniswap Pools page.
Uniswap / Auto-Rebalance
Position out of range
Symptom: The position shows as "out of range" and is not earning fees.
Resolution:
- The
UNISWAP_AUTO_REBALANCEcron should handle this automatically if the deviation exceeds the threshold. - For immediate action, perform a manual rebalance to re-center the position around the current oracle price.
- Adjust
priceBandPercentif the position goes out of range too frequently.
Liquidity is zero after mint
Symptom: A mint position operation succeeds but the position shows liquidity = 0.
Cause: The entire tick range is above or below the current price, and only one token was provided. The amounts may have been too small to produce meaningful liquidity.
Resolution:
- Verify the tick range makes sense for the current price.
- For out-of-range positions, ensure a sufficient amount of the required single token was provided.
- Backend validates
liquidity > 0nbefore sending -- if you see this error message, adjust amounts or range.
TVL showing incorrect value
Symptom: TVL displayed on the dashboard does not match expectations.
Cause: TVL is approximated from active liquidity at the current tick (StateView.getLiquidity). This only counts liquidity concentrated around the current price, not all liquidity across all ranges.
Resolution: This is expected behavior. For a more accurate TVL, sum all position values. The dashboard shows active liquidity as a proxy.
Unwanted auto-rebalance triggering
Symptom: The auto-rebalance fires too frequently, consuming gas.
Resolution:
- Increase
rebalanceTriggerPercenton the bot configuration to require a larger deviation before triggering. - Increase
priceBandPercentto create wider positions that stay in range longer.
Bridge
Tokens not arriving at destination
Symptom: Bridge TX was sent but tokens have not arrived on the destination chain.
Diagnosis:
- Check the source chain TX on the block explorer -- did it succeed?
- Check LayerZero Scan (https://layerzeroscan.com) for the message status.
- Check the
BRIDGE_TX_SYNCcron for errors.
Resolution:
- LayerZero messages can take a few minutes to be relayed. Wait 5-10 minutes.
- If the message is stuck, check LayerZero Scan for the specific message hash.
- If the source TX reverted, the tokens were not locked/burned and remain in the sender's wallet.
Insufficient fee error
Symptom: Bridge transaction fails with an insufficient fee error.
Cause: The native fee quoted by quoteSend was too low, or gas prices spiked between quote and send.
Resolution:
- Retry the bridge operation -- the quote will reflect current gas prices.
- Ensure the wallet has enough native token (ETH on Base, MATIC on Polygon) for the LayerZero fee.
Database
Migration fails on deploy
Symptom: ECS task fails to start because a migration threw an error.
Common causes:
- Column already exists (partial previous run): Wrap in
hasColumncheck. - Table already exists: Wrap in
hasTablecheck. - Foreign key references non-existent row: Use check-before-insert.
Resolution:
- Check CloudWatch logs for the specific migration error.
- Fix the migration file.
- Re-deploy.
Migration lock stuck
Symptom: Migration table is already locked error prevents migrations from running.
Cause: A previous migration crashed mid-execution without releasing the lock.
Resolution:
Code
Or:
Code
Then retry the migration.
Frontend
WalletConnect ProjectNotFound (code 3000)
Symptom: WalletConnect modal fails to load, console shows ProjectNotFound error code 3000.
Cause: VITE_WALLET_CONNECT_PROJECT_ID was not set at build time, so the bundle contains "development" as the project ID.
Resolution:
- Add the WalletConnect project ID as a GitHub Secret (e.g.,
PRODUCTION_WALLET_CONNECT_PROJECT_ID). - Pass it in the
env:block of the Build step in.github/workflows/deploy.yml. - Re-deploy the frontend.
Note: The WalletConnect project ID is public by design (like a Stripe publishable key). You can allowlist your domain at https://cloud.reown.com to prevent quota abuse.
MetaMask console error on Safe wallet
Symptom: Console errors related to MetaMask when using Safe{Wallet}.
Cause: Safe injects its own provider which can conflict with MetaMask detection.
Resolution: These errors are cosmetic and do not affect functionality. Safe handles transactions through its own signing flow, not MetaMask.
Blank page after deploy
Symptom: Frontend shows a blank white page after a new deploy.
Diagnosis:
- Open browser dev tools > Console for JavaScript errors.
- Check if the S3 bucket has the new files.
- Check if CloudFront invalidation completed.
Resolution:
- If S3 has old files: the deploy step failed. Check GitHub Actions logs.
- If CloudFront cache is stale: run a manual invalidation:
aws cloudfront create-invalidation --distribution-id XXXXX --paths "/*". - If there are JS errors: likely a missing
VITE_*env var. Check the build logs for warnings about undefined variables.