hpyhacking/peatio · warning · Grape::Exceptions::Validation

1001

1001

Error message

must be in range: #{@range}

What it means

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.

Source

Thrown at app/api/api_v2/validations.rb:13

module APIv2
  module Validations
    class Range < ::Grape::Validations::Validator

      def initialize(attrs, options, required, scope)
        @range    = options
        @required = required
        super
      end

      def validate_param!(attr_name, params)
        if (params[attr_name] || @required) && !@range.cover?(params[attr_name])
          raise Grape::Exceptions::Validation, param: @scope.full_name(attr_name), message: "must be in range: #{@range}"
        end
      end

    end
  end
end

View on GitHub (pinned to dab8641137)

Solutions

  1. Clamp limit into 1..1000 before the call, or omit it entirely — server defaults are 100 for /orders and 50 for /trades.
  2. Paginate with page + limit instead of raising limit.
  3. Validate the parameter client-side (integer, 1..1000) before building the signed payload.

Example fix

# before
get '/orders', market: 'btcusd', limit: 5000   # 1001: limit must be in range: 1..1000

# after
limit = [[limit.to_i, 1].max, 1000].min
get '/orders', market: 'btcusd', limit: limit, page: page
Defensive patterns

Strategy: validation

Validate before calling

# Ruby: clamp before building the signed request
limit = [[params[:limit].to_i, 1].max, 1000].min
client.get '/api/v2/orders', market: 'btcusd', limit: limit, page: page

Type guard

// TypeScript: narrow a limit before it reaches the request builder
const isValidLimit = (v: unknown): v is number =>
  typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 1000;

Try / catch

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.

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hpyhacking/peatio@dab8641137 (2026-08-23). Data as JSON: /api/errors/1545997e0c9b7ffb. Report an issue: GitHub.