{"record":{"id":"78f6db89500014ce","repo":"hpyhacking/peatio","slug":"2002-78f6db","errorCode":"2002","errorMessage":"Market is not deep enough","messagePattern":"Market is not deep enough","errorType":"exception","errorClass":"RuntimeError","httpStatus":400,"severity":"error","filePath":"app/models/order.rb","lineNumber":153,"sourceCode":"\n  FUSE = '0.9'.to_d\n  def estimate_required_funds(price_levels)\n    required_funds = Account::ZERO\n    expected_volume = volume\n\n    start_from, _ = price_levels.first\n    filled_at     = start_from\n\n    until expected_volume.zero? || price_levels.empty?\n      level_price, level_volume = price_levels.shift\n      filled_at = level_price\n\n      v = [expected_volume, level_volume].min\n      required_funds += yield level_price, v\n      expected_volume -= v\n    end\n\n    raise \"Market is not deep enough\" unless expected_volume.zero?\n    raise \"Volume too large\" if (filled_at-start_from).abs/start_from > FUSE\n\n    required_funds\n  end\n\nend\n","sourceCodeStart":135,"sourceCodeEnd":160,"githubUrl":"https://github.com/hpyhacking/peatio/blob/dab8641137c008928c835409342519bfef4eae7f/app/models/order.rb#L135-L160","documentation":"Peatio error surfaced as APIv2 code 2002 (HTTP 400), \"Failed to create order. Reason: Market is not deep enough\". For a MARKET order, Ordering#submit computes locked funds via compute_locked, which calls estimate_required_funds (app/models/order.rb) to walk the opposite side of the shared order book — Global[currency].asks for a market buy (OrderBid), .bids for a market sell (OrderAsk) — consuming level volumes until the requested volume is covered. If the entire book holds less volume than requested, expected_volume never reaches zero and the method raises RuntimeError \"Market is not deep enough\", which the API helper rescues into CreateOrderError.","triggerScenarios":"POST /api/v2/orders with ord_type=market and volume exceeding the counter side's total depth (buy 100 BTC when all asks sum to 10 BTC); a thin or newly listed market; the moments right after a matching-engine restart while order books are still being rebuilt from the database.","commonSituations":"Bots sizing positions from another exchange's liquidity; market orders on low-volume pairs; test environments with sparse seeded orders; confusion with the sibling 2002 error 'Volume too large' — that one means depth exists but the price walk exceeded the 90% FUSE.","solutions":["Fetch the depth first (GET /api/v2/order_book) and cap market-order volume below the counter side's total volume.","Split the market order into smaller chunks spaced over time so the book can refill.","Use ord_type=limit with an acceptable price — limit orders lock price*volume and never run the depth estimate.","If you operate the exchange, verify the matching daemon has rebuilt its order books after a restart before accepting market orders."],"exampleFix":"# before\npost '/orders', market: 'btcusd', side: 'buy', ord_type: 'market', volume: '100'\n\n# after: cap market-order volume to half the visible ask depth\ndepth  = get '/order_book', market: 'btcusd'\ntotal  = depth['asks'].sum { |_p, v| v.to_d }\nvolume = [wanted, total / 2].min\npost '/orders', market: 'btcusd', side: 'buy', ord_type: 'market', volume: volume.to_s('F')","handlingStrategy":"validation","validationCode":"# Ruby: verify counter-side depth covers the market order before submitting\ndepth = client.get '/api/v2/order_book', market: 'btcusd'\nasks = depth['asks']                            # [[price, volume], ...] for a buy\ntotal = asks.sum { |_p, v| v.to_d }\nraise \"only #{total} available, wanted #{volume}\" if total < volume.to_d\nclient.post '/api/v2/orders', market: 'btcusd', side: 'buy',\n            ord_type: 'market', volume: volume.to_s('F')","typeGuard":"// TypeScript: shape guard for the order book before summing depth\nconst isOrderBookSide = (v: unknown): v is [string, string][] =>\n  Array.isArray(v) && v.every(l => Array.isArray(l) && l.length === 2 &&\n    typeof l[0] === 'string' && typeof l[1] === 'string');","tryCatchPattern":"On code 2002 whose Reason includes 'Market is not deep enough': fetch depth, cap volume below total counter-side volume (or switch to a limit order), and resubmit once; do not blind-retry the original volume.","preventionTips":["Size market orders from live depth (GET /api/v2/order_book), never from another venue's liquidity.","On thin markets prefer limit orders, which skip the depth estimate entirely.","Split large market orders into time-spaced chunks smaller than visible depth.","Right after an engine restart, probe depth first — books repopulate lazily and early market orders overestimate available liquidity."],"tags":["peatio","market-order","liquidity","order-book","insufficient-depth"],"backgroundTag":"insufficient-market-liquidity","analyzedSha":"dab8641137c008928c835409342519bfef4eae7f","analyzedAt":"2026-08-23T09:59:18.005Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}