mislav/will_paginate · error · RangeError
invalid #{name}: #{value.inspect}
Error message
invalid #{name}: #{value.inspect} What it means
WillPaginate::PageNumber coerces its input with Integer(value) and enforces a range: page numbers must be >= 1, offsets must be 0..BIGINT (2^63-1, the SQL bigint ceiling). Violations raise RangeError 'invalid page/offset: ...', and any coercion failure (ArgumentError/TypeError) is extended with the WillPaginate::InvalidPage module before re-raising, so all bad-input cases are catchable as WillPaginate::InvalidPage.
Source
Thrown at lib/will_paginate/page_number.rb:17
require 'forwardable'
module WillPaginate
# a module that page number exceptions are tagged with
module InvalidPage; end
# integer representing a page number
class PageNumber < Numeric
# a value larger than this is not supported in SQL queries
BIGINT = 9223372036854775807
extend Forwardable
def initialize(value, name)
value = Integer(value)
if 'offset' == name ? (value < 0 or value > BIGINT) : value < 1
raise RangeError, "invalid #{name}: #{value.inspect}"
end
@name = name
@value = value
rescue ArgumentError, TypeError, RangeError => error
error.extend InvalidPage
raise error
end
def to_i
@value
end
def_delegators :@value, :coerce, :==, :<=>, :to_s, :+, :-, :*, :/, :to_json
def inspect
"#{@name} #{to_i}"
end
View on GitHub (pinned to 50017c3eb0)
Solutions
- Sanitize the param at the boundary: page = params[:page].presence && params[:page].to_i; page = nil if page && page < 1 — nil coerces to page 1 downstream
- Rescue WillPaginate::InvalidPage in the controller and fall back to page 1 or render a 404
- Clamp derived offsets to 0..WillPaginate::PageNumber::BIGINT before passing them to the offset API
Example fix
// before @posts = Post.page(params[:page]) // after raw = params[:page].to_s page = raw.match?(/\A[1-9]\d*\z/) ? raw.to_i : 1 @posts = Post.page(page)
Defensive patterns
Strategy: try-catch
Validate before calling
raw = params[:page].to_s page = raw.match?(/\A[1-9]\d*\z/) ? raw.to_i : nil # nil -> page 1 downstream page = nil if page && page > WillPaginate::PageNumber::BIGINT @posts = Post.page(page)
Type guard
def valid_page_number?(value) s = value.to_s s.match?(/\A[1-9]\d*\z/) && s.to_i <= WillPaginate::PageNumber::BIGINT end
Try / catch
begin @posts = Post.page(params[:page]).per(10) rescue WillPaginate::InvalidPage # RangeError/ArgumentError/TypeError tagged by PageNumber redirect_to(posts_path(page: 1)) and return # or render plain: 'Not Found', status: 404 end
Prevention
- Sanitize :page once in a controller concern: digits-only, >= 1, capped at a sane ceiling (e.g. 10_000), nil otherwise
- Never pass params[:page] straight into page()/paginate() on public endpoints — bots routinely probe ?page=0 and junk
- Rescue WillPaginate::InvalidPage globally in a controller around_action to render 404 instead of a 500
When it happens
Trigger: Model.page(params[:page]) with params[:page] = 'abc' (Integer('abc') -> ArgumentError), '0' or 0 or -3 (below the minimum of 1), or a URL-crafted huge value like 99999999999999999999 (Integer works but exceeds nothing... only offsets compare to BIGINT; a page that huge is fine for page, but offset = (page-1)*per_page can exceed BIGINT and blow up in the offset branch). Also .page(1.5) style garbage from form input.
Common situations: Public-facing list endpoints where :page comes straight from the query string and is never sanitized; scrapers/bots probing ?page=0 or ?page=-1; user-typed junk in a search box bound to the page param; wrapping arithmetic that computes an offset overflow.
Related errors
- :page parameter required
- unsupported parameters: %p
- :renderer not specified
- The #{collection_name} variable appears to be empty. Did you
- DEPRECATION WARNING: #{message} (called from #{offending_lin
AI-assisted analysis of mislav/will_paginate@50017c3eb0 (2026-08-21).
Data as JSON: /api/errors/3d2ac631f0bd3ea3.
Report an issue: GitHub.