{"record":{"id":"1545997e0c9b7ffb","repo":"hpyhacking/peatio","slug":"1001","errorCode":"1001","errorMessage":"must be in range: #{@range}","messagePattern":"must be in range: #(.+?)","errorType":"validation","errorClass":"Grape::Exceptions::Validation","httpStatus":400,"severity":"warning","filePath":"app/api/api_v2/validations.rb","lineNumber":13,"sourceCode":"module APIv2\n  module Validations\n    class Range < ::Grape::Validations::Validator\n\n      def initialize(attrs, options, required, scope)\n        @range    = options\n        @required = required\n        super\n      end\n\n      def validate_param!(attr_name, params)\n        if (params[attr_name] || @required) && !@range.cover?(params[attr_name])\n          raise Grape::Exceptions::Validation, param: @scope.full_name(attr_name), message: \"must be in range: #{@range}\"\n        end\n      end\n\n    end\n  end\nend\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/hpyhacking/peatio/blob/dab8641137c008928c835409342519bfef4eae7f/app/api/api_v2/validations.rb#L1-L20","documentation":"Peatio APIv2 error code 1001 (HTTP 400). APIv2::Validations::Range is a custom Grape validator bound to the `range:` option; validate_param! raises Grape::Exceptions::Validation unless @range.cover?(value). It guards the `limit` parameter on GET /api/v2/orders and the shared trade_filters (both `range: 1..1000`), and the rescue_from handler renders {error: {code: 1001, message: \"limit must be in range: 1..1000\"}}. The guard `(params[attr_name] || @required)` means an absent optional parameter skips the check — only a supplied out-of-range value fails.","triggerScenarios":"GET /api/v2/orders?market=btcusd&limit=0, limit=-1, or limit=1001 and beyond; GET /api/v2/trades (and other endpoints using trade_filters) with limit outside 1..1000; any client that encodes 'unlimited' as a very large or zero limit value.","commonSituations":"Porting a bot from an exchange whose page-size cap is 5000; passing limit=0 intending 'use default'; page-size values shared across APIs with different caps; non-integer strings that fail Integer coercion before the range check is even reached.","solutions":["Clamp limit into 1..1000 before the call, or omit it entirely — server defaults are 100 for /orders and 50 for /trades.","Paginate with page + limit instead of raising limit.","Validate the parameter client-side (integer, 1..1000) before building the signed payload."],"exampleFix":"# before\nget '/orders', market: 'btcusd', limit: 5000   # 1001: limit must be in range: 1..1000\n\n# after\nlimit = [[limit.to_i, 1].max, 1000].min\nget '/orders', market: 'btcusd', limit: limit, page: page","handlingStrategy":"validation","validationCode":"# Ruby: clamp before building the signed request\nlimit = [[params[:limit].to_i, 1].max, 1000].min\nclient.get '/api/v2/orders', market: 'btcusd', limit: limit, page: page","typeGuard":"// TypeScript: narrow a limit before it reaches the request builder\nconst isValidLimit = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 1000;","tryCatchPattern":"If a 1001 'must be in range' response still arrives, re-issue the identical request once with limit clamped to the range stated in the message; do not retry unchanged.","preventionTips":["Centralize a clampPeatioLimit() helper in one request builder so every paginated call is covered.","Omit optional limit to accept server defaults (100 for /orders, 50 for /trades) in configs that never need bigger pages.","Add an integration test that paginates with the boundary values 1 and 1000.","Never overload limit to mean page size across exchanges — keep per-exchange caps in config."],"tags":["peatio","grape","validation","query-params","pagination"],"backgroundTag":"request-validation-failed","analyzedSha":"dab8641137c008928c835409342519bfef4eae7f","analyzedAt":"2026-08-23T09:59:18.005Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}