openfinance-troubleshooting
OpenFinance Troubleshooting
Error → diagnosis → fix. Check here before assuming an issue is a server-side bug: most failures are known and have been hit before.
Polymarket
POST /agent/polymarket/approvals shows max but CLOB returns allowance: 0
Root cause: approval targeted the wrong USDC contract or wrong exchange spender.
Polymarket on Polygon enforces allowance against USDC.e
(0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174), not pUSD or native USDC. And
orders settle on the V1 exchange (0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E),
not V2 — even though the SDK is clob-client-v2. The CLOB's GET /version
returns 1.
Fix: Call POST /agent/polymarket/approvals with {negRisk: true} if the
market is neg-risk. The server approves USDC.e on V1 spenders. If you
previously approved a different token manually, those allowances are stuck
against the wrong token.
POST /agent/polymarket/order/market returns 404 upstream (limit orders work)
Root cause: SDK's createMarketOrder calls ensureBuilderFeeRateCached
which does unauthenticated GET /fees/builder-fees/<code>. That endpoint
404s until Polymarket's fee service has the builder code onboarded.
Fix: Already patched — the backend catches the 404 and caches a zero-rate entry. If you still see this, the deployment is behind. Retry passes through after the patch is live.
Order failed: tick size on a price that looks right
Root cause: Market's minimum tick size is smaller than 0.01 (the default).
Passing 0.01 when the market needs 0.001 or 0.0001 rejects.
Fix: Pass tickSize: "0.001" or "0.0001" explicitly in the request body.
Read the market's min tick from GET /agent/polymarket/markets/cid/:conditionId.
Order size below minimum
Polymarket requires ~$1 USDC minimum notional. price=0.05, size=10 = $0.50
notional → rejected.
Fix: Increase size so price * size >= 1.
Relay
InstructionFallbackNotFound (Custom:101) on Solana-origin execute
Root cause: Instruction data decoded with wrong encoding. Relay returns
Solana instruction data as hex (no 0x prefix), not base64. Early
backend versions decoded as base64 → garbage bytes → depository rejected.
Fix: Already patched. First 8 bytes of a correctly-decoded instruction
should match Relay's discriminator (e.g. 0b9c60da27a3b413).
Blockhash not found repeatedly on Solana execute
Root cause: Privy's signAndSendTransaction uses a different RPC than
the one that issued the blockhash. Cross-RPC divergence — no retry fixes it.
Fix: Already patched — backend now uses Privy's signTransaction (sign
only) and broadcasts via our own RPC with skipPreflight: true. If you still
see it, set SOLANA_RPC_URL to a dedicated provider (Helius/Triton/QuickNode)
— the public api.mainnet-beta.solana.com is heavily throttled.
401 No valid authorization signatures were provided on Solana execute
Root cause: User's Solana wallet isn't delegated to the app. EVM delegation doesn't transfer.
Fix: See openfinance-setup step 2 — frontend must call
useDelegatedActions().delegateWallet({ address: solanaAddress, chainType: 'solana' }).
Server catches this now and returns 412 with a clearer message.
POST /agent/relay/execute says "User has no Solana wallet provisioned"
Root cause: Privy app isn't configured to create Solana embedded wallets, or the specific user logged in before Solana was enabled.
Fix: Enable Solana in Privy dashboard; existing users may need to trigger wallet creation.
Gas topup forced off unexpectedly
Expected behavior, not a bug. When either origin or destination chain ID
is Solana (792703809), topupGas is forced to false server-side. Topup
doesn't work cleanly for EVM↔SVM routes.
Hyperliquid
Insufficient perp account value
Root cause: Perp trading requires margin. USDC on Hyperliquid isn't automatically available for perp trading.
Fix: POST /agent/trading/transfer to move USDC between spot and perp
accounts, or deposit first via GET /agent/trading/deposit-address.
WebSocket data is stale
Root cause: The backend maintains one shared connection to
wss://api.hyperliquid.xyz/ws and caches per-channel. If the connection dropped
and reconnected, the first few messages after reconnect may be missing.
Fix: The backend auto-reconnects after 3s. Retry the read; cache fills within a few seconds. If persistent, something is wrong with outbound WS from the server host.
Order rejected: price out of bounds
Root cause: Hyperliquid rejects prices too far from the current mid (price bands). Typically ±5-10% depending on asset.
Fix: Read mid via GET /agent/trading/market/mids and set price within
bounds. For aggressive fills, use limit orders crossing the book but within
the band.
General principles
- Check
GET /agent/walletsfirst when anything auth-related fails. It tells you if delegation is in place and which chains are provisioned. - On-chain state != CLOB/Relay state. Approvals can show on-chain but still report 0 upstream because of token/contract mismatches. Don't trust "on-chain says X" without also checking the service's view.
- When in doubt, read the error string verbatim — don't paraphrase. Many
errors have specific signatures (
Custom:101vsCustom:6000) that map to exactly one fix.
More from openfinance-tech/skills
openfin-relay
Cross-chain bridging, swapping, and "bridge+call" via Relay through the OpenFinance backend. Use whenever the user wants to move tokens between chains or execute a destination-chain transaction funded from another chain. Triggers: "bridge X from Y to Z", "move my USDC to Base / Arbitrum / Optimism / Polygon / Solana", "swap ETH for USDC on Base", "cross-chain swap", "bridge and call", "how do I get to Solana / back from Solana", "my USDC is stuck on Solana", EVM-to-EVM, EVM-to-Solana, Solana-to-EVM, Bitcoin bridge, gas topup on destination, native-token sentinel 0x0, relay quote/preview/execute flow, poll intent status. Covers POST /agent/relay/quote, POST /agent/relay/execute, GET /agent/relay/status. Includes the chainId cheatsheet (1/137/8453/10/42161/... and Solana 792703809 specifically), tradeType semantics (EXACT_INPUT / EXACT_OUTPUT / EXPECTED_OUTPUT), why topupGas is auto-disabled on Solana routes, and bridge+call payloads (txs array). Use together with openfin-setup (API key check) and openfin-troubleshooting (Blockhash not found, Custom:101, 412 setup-incomplete on Solana origin).
24openfin-polymarket
Complete Polymarket playbook covering research and trading on the world's largest prediction market. Use this for ANY Polymarket task. Deposit-wallet model (CRITICAL): Polymarket's CLOB rejects raw EOAs as makers, so each user has a deterministic per-EOA "deposit wallet" smart contract that holds pUSD, carries allowances, and is named as `funder`/`maker`/`signer` on signed orders (POLY_1271 / EIP-1271). pUSD sent directly to the EOA is stranded for trading until it reaches the deposit wallet. Always call `GET /agent/polymarket/deposit-wallet` to get the right address before quoting "where do I deposit", checking balance, or running position queries — and pass the deposit-wallet address (NOT the EOA) as `:address` for `/user/:address/*` lookups. Research triggers: finding events ("what's happening in politics", "show me election odds", "NBA finals odds", "BTC to 200k markets", "IPL / FIFA / UFC / F1 betting markets"), listing markets with filters, searching by keyword, reading orderbooks, mid prices, spreads, last trade prices, recent trades, open interest, volume, liquidity, and any user's positions/portfolio/PnL by address. Deposit triggers: "where do I deposit on Polymarket", "what's my Polymarket address", "send pUSD to Polymarket", "Polymarket deposit wallet", "is my deposit wallet deployed". Trading triggers: place a bet on YES or NO, buy/sell outcomes, limit orders (GTC/GTD), market orders (FOK/FAK), batch orders, cancel one/many/all orders, check and set on-chain pUSD and CTF approvals, neg-risk (multi-outcome) markets, tick size handling (0.01/0.001/0.0001), and builder-code attribution. Covers all routes under /agent/polymarket/* (events, markets, search, orderbook, price, prices, spread, last-trade-price, trades, market/:id/open-interest|volume|liquidity|trades, user/:address/positions|trades|portfolio|pnl, deposit-wallet, order, order/market, orders, order/:id, order/:id/scoring, approvals, builder/*). Use when the user mentions Polymarket, prediction markets, event betting, binary outcomes, probability markets, YES/NO tokens, conditional tokens, or politics/sports/crypto/culture odds. Prerequisite: openfin-setup for trading.
24openfin-setup
Auth check for the OpenFinance backend — confirms an API key is available before any other OpenFinance skill runs. Use FIRST whenever the user is about to call any /agent/* route (Polymarket, Hyperliquid, Relay), is hitting 401/412, or hasn't traded yet in this session. Triggers on "how do I get started", "API key is required", "Invalid API key", "401/412 from /agent/*", "set up OpenFinance", or any first call into a trading skill. Resolves the key from `OPENFINANCE_API_KEY` (or equivalent env / user-supplied value), confirms the format (`open_…`), verifies via GET /agent/wallets, and otherwise points the user to https://openfinance.tech to issue one.
23openfin-hyperliquid
>-
23openfin-troubleshooting
>-
23openfin-onchain
Multi-chain on-chain token data — metadata, wallet portfolios, balances, and USD prices — across 100+ EVM and Solana networks via the OpenFinance /agent/onchain/* routes (Uniblock-backed). Use whenever an agent needs to look up what a token is, what an arbitrary address holds, or what something costs in USD before quoting / trading / displaying. Triggers: "what is token 0x...", "lookup token name and decimals", "show me wallet 0x... portfolio", "what does this address hold", "USDC balance on Polygon / Base / Arbitrum / Optimism", "price of ETH / WBTC / SOL right now", "USD price of <contract>", "batch token metadata", "batch USD prices", "is this contract a token", "wallet NFTs", "wallet holdings on chainId X". Covers GET /agent/onchain/token/metadata, GET /agent/onchain/token/portfolio (native + fungibles + NFTs), GET /agent/onchain/token/balances (lighter — no NFTs, paginated), GET /agent/onchain/token/price (single or comma-separated batch). Read-only; no signing. Each call requires `x-api-key: open_…`. Prerequisite: openfin-setup. Pair with openfin-relay when the user wants to act on what they hold.
14