{"record":{"id":"956ddf3f64fdb383","repo":"hpyhacking/peatio","slug":"2004","errorCode":"2004","errorMessage":"Order##{id} doesn't exist.","messagePattern":"Order##(.+?) doesn't exist\\.","errorType":"exception","errorClass":"APIv2::OrderNotFoundError","httpStatus":404,"severity":"error","filePath":"app/api/api_v2/orders.rb","lineNumber":32,"sourceCode":"    end\n    get \"/orders\" do\n      orders = current_user.orders\n        .order(order_param)\n        .with_currency(current_market)\n        .with_state(params[:state])\n        .page(params[:page])\n        .per(params[:limit])\n\n      present orders, with: APIv2::Entities::Order\n    end\n\n    desc 'Get information of specified order.', scopes: %w(history trade)\n    params do\n      use :auth, :order_id\n    end\n    get \"/order\" do\n      order = current_user.orders.where(id: params[:id]).first\n      raise OrderNotFoundError, params[:id] unless order\n      present order, with: APIv2::Entities::Order, type: :full\n    end\n\n    desc 'Create multiple sell/buy orders.', scopes: %w(trade)\n    params do\n      use :auth, :market\n      requires :orders, type: Array do\n        use :order\n      end\n    end\n    post \"/orders/multi\" do\n        orders = create_orders params[:orders]\n        present orders, with: APIv2::Entities::Order\n    end\n\n    desc 'Create a Sell/Buy order.', scopes: %w(trade)\n    params do\n      use :auth, :market, :order","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/hpyhacking/peatio/blob/dab8641137c008928c835409342519bfef4eae7f/app/api/api_v2/orders.rb#L14-L50","documentation":"Peatio APIv2 error code 2004 (HTTP 404), raised by GET /api/v2/order. The endpoint runs current_user.orders.where(id: params[:id]).first, so the lookup covers only orders owned by the authenticated member. When no own order carries that id, it raises OrderNotFoundError and returns {error: {code: 2004, message: \"Order##{id} doesn't exist.\"}}. An order that exists under a different member is indistinguishable from one that never existed.","triggerScenarios":"GET /api/v2/order signed with account A's access key while the id was created by account B; a typo'd, truncated, or zero id; an id copied from another environment (staging vs production) or from data predating a database restore. The token must carry the history or trade scope, and the id must be an integer (params :order_id requires type Integer).","commonSituations":"A bot replays cached order ids from a testnet deployment against production; two API keys for two accounts and the client signs with the wrong one; ids serialized through JavaScript lose precision above 2^53; long-gone orders still referenced by a local cache after a DB purge.","solutions":["List your own orders with GET /api/v2/orders (use state and page filters) and confirm the id appears under the same access key that signs the request.","Verify the access_key belongs to the member that created the order; switch to the correct key or re-create the order under the current account.","Keep order ids as strings end to end so they are not float-rounded or truncated before the call.","Treat code 2004 as terminal: do not retry the same request; drop the stale local reference to that order."],"exampleFix":"// before\nconst order = await peatio.get('/order', { id }); // 2004 => request fails, bot crashes\n\n// after\nconst res = await peatio.get('/order', { id }).catch(e => e);\nif (res?.error?.code === 2004) {\n  // not owned by this account or no longer referenceable\n  forgetOrder(id);\n} else {\n  useOrder(res);\n}","handlingStrategy":"validation","validationCode":"# Ruby client: confirm the id belongs to the signing account before GET /order\nmine = client.get '/api/v2/orders', market: 'btcusd', state: 'wait'   # own orders only\nown_ids = mine.map { |o| o['id'] }\nraise \"id #{id} not owned by this account\" unless own_ids.include?(id)\norder = client.get '/api/v2/order', id: id","typeGuard":"// TypeScript: order ids are opaque positive integers — narrow before use\nconst isOrderId = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isInteger(v) && v > 0;","tryCatchPattern":"Catch the HTTP 404 whose body.error.code === 2004 and treat it as terminal: remove the order from local state and continue; never retry the same id unchanged.","preventionTips":["Keep order ids as strings end to end to avoid 2^53 precision loss in JavaScript.","Use one access key per account and assert the key's member matches the order owner before querying.","Cache order state from GET /api/v2/orders and drop entries you no longer see instead of probing them one by one.","Scope check: the token needs 'history' or 'trade' — a missing scope surfaces as 2011, not 2004, so verify scopes separately."],"tags":["peatio","apiv2","order-not-found","http-404","grape"],"backgroundTag":"resource-not-found","analyzedSha":"dab8641137c008928c835409342519bfef4eae7f","analyzedAt":"2026-08-23T09:59:18.005Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}