{"record":{"id":"45054fd7b81db6f9","repo":"hpyhacking/peatio","slug":"2012","errorCode":"2012","errorMessage":"Deposit##txid=#{txid} doesn't exist.","messagePattern":"Deposit##txid=#(.+?) doesn't exist\\.","errorType":"exception","errorClass":"APIv2::DepositByTxidNotFoundError","httpStatus":404,"severity":"error","filePath":"app/api/api_v2/deposits.rb","lineNumber":31,"sourceCode":"      optional :limit, type: Integer, range: 1..100, default: 3, desc: \"Set result limit.\"\n      optional :state, type: String, values: Deposit::STATES.map(&:to_s)\n    end\n    get \"/deposits\" do\n      deposits = current_user.deposits.limit(params[:limit]).recent\n      deposits = deposits.with_currency(params[:currency]) if params[:currency]\n      deposits = deposits.with_aasm_state(params[:state]) if params[:state].present?\n\n      present deposits, with: APIv2::Entities::Deposit\n    end\n\n    desc 'Get details of specific deposit.'\n    params do\n      use :auth\n      requires :txid\n    end\n    get \"/deposit\" do\n      deposit = current_user.deposits.find_by(txid: params[:txid])\n      raise DepositByTxidNotFoundError, params[:txid] unless deposit\n\n      present deposit, with: APIv2::Entities::Deposit\n    end\n\n    desc 'Where to deposit. The address field could be empty when a new address is generating (e.g. for bitcoin), you should try again later in that case.'\n    params do\n      use :auth\n      requires :currency, type: String, values: Currency.all.map(&:code), desc: \"The account to which you want to deposit. Available values: #{Currency.all.map(&:code).join(', ')}\"\n    end\n    get \"/deposit_address\" do\n      current_user.ac(params[:currency]).payment_address.to_json\n    end\n  end\nend\n","sourceCodeStart":13,"sourceCodeEnd":46,"githubUrl":"https://github.com/hpyhacking/peatio/blob/dab8641137c008928c835409342519bfef4eae7f/app/api/api_v2/deposits.rb#L13-L46","documentation":"Error code 2012 (DepositByTxidNotFoundError) is raised by GET /api/v2/deposit when current_user.deposits.find_by(txid: params[:txid]) returns nil. The finder is scoped through the authenticated member, so the deposit must both exist in the deposits table AND belong to the access key's account; a txid owned by another user (or recorded by another exchange) produces the same error as a nonexistent one.","triggerScenarios":"Querying a txid that belongs to a different account or a different exchange; a typo'd or truncated txid; chain-specific formatting differences (case sensitivity, tag/memo-based chains recording an internal txid that differs from the on-chain hash); a deposit already broadcast but not yet collected and persisted by the deposit worker.","commonSituations":"Ops scripts copying a txid from an explorer or another exchange's withdrawal page while querying this account's API; support tooling checking the wrong member; polling seconds after broadcasting before confirmations/collection complete.","solutions":["List the authenticated account's own deposits via GET /api/v2/deposits and copy the exact txid value the API returns","If the deposit is brand new, wait for collection/confirmations and retry the lookup","Confirm the deposit address actually belongs to this account (GET /api/v2/deposit_addresses) — if not, you are querying the wrong member's data"],"exampleFix":"# before — txid taken from an external explorer/another exchange\nget '/api/v2/deposit', params: auth_params.merge(txid: explorer_txid)\n\n# after — resolve txid from this account's own deposit history first\ndeposits = get '/api/v2/deposits', params: auth_params\ntxid = deposits.find { |d| d['currency'] == 'btc' }&.dig('txid')\nraise 'no deposit recorded yet' unless txid\nget '/api/v2/deposit', params: auth_params.merge(txid: txid)","handlingStrategy":"validation","validationCode":"# Resolve the txid from this account's own history before the single lookup\ndeposits = get '/api/v2/deposits', params: auth_params.merge(currency: 'btc')\nowned = deposits.any? { |d| d['txid'] == params[:txid] }\nreturn unless owned  # skip the call; it would raise 2012\nget '/api/v2/deposit', params: auth_params.merge(txid: params[:txid])","typeGuard":"# Ruby: the txid is valid for this account only if membership resolves\nowned_txids = Set.new(deposits.map { |d| d['txid'] })\nowned_txids.include?(candidate_txid)","tryCatchPattern":"Treat 2012 as a terminal lookup miss for this account: report 'not found for this account' rather than retrying — a foreign or unpersisted txid will never appear under the authenticated member.","preventionTips":["Source txids from the account's own /deposits listing, never from explorers or other exchanges' withdrawal pages","For tag/memo chains, store the receiving side's recorded txid, which can differ from the sending exchange's hash","When polling fresh deposits, back off until collection finishes instead of hammering /deposit"],"tags":["ruby","api","deposits","not-found","exchange"],"backgroundTag":"resource-not-found","analyzedSha":"dab8641137c008928c835409342519bfef4eae7f","analyzedAt":"2026-08-23T09:59:18.005Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}