railsadminteam/rails_admin · error · ArgumentError
Unsupported sort value: #{options[:sort]}
Error message
Unsupported sort value: #{options[:sort]} What it means
RailsAdmin's ActiveRecord adapter builds the ORDER BY clause in sort_scope (lib/rails_admin/adapters/active_record.rb:160). options[:sort] must be a String/Symbol column name, an Array of columns, or a one-level Hash of {table_name => column}; any other class raises ArgumentError before SQL is generated. The value normally comes from MainController#get_sort_hash (app/controllers/rails_admin/main_controller.rb:66), which uses the matched field's sort_column (a String) or falls back to the model's list.sort_by configuration.
Source
Thrown at lib/rails_admin/adapters/active_record.rb:171
if primary_key.is_a? Array
options[:bulk_ids].map { |id| primary_key_scope(scope, id) }.reduce(&:or)
else
scope.where(primary_key => options[:bulk_ids])
end
end
def sort_scope(scope, options)
direction = options[:sort_reverse] ? :asc : :desc
case options[:sort]
when String, Symbol
scope.reorder("#{options[:sort]} #{direction}")
when Array
scope.reorder(options[:sort].zip(Array.new(options[:sort].size) { direction }).to_h)
when Hash
scope.reorder(options[:sort].map { |table_name, column| "#{table_name}.#{column}" }.
zip(Array.new(options[:sort].size) { direction }).to_h)
else
raise ArgumentError.new("Unsupported sort value: #{options[:sort]}")
end
end
class WhereBuilder
def initialize(scope)
@statements = []
@values = []
@tables = []
@scope = scope
end
def add(field, value, operator)
field.searchable_columns.flatten.each do |column_infos|
statement, value1, value2 = StatementBuilder.new(column_infos[:column], column_infos[:type], value, operator, @scope.connection.adapter_name).to_statement
@statements << statement if statement.present?
@values << value1 unless value1.nil?
@values << value2 unless value2.nil?
table, column = column_infos[:column].split('.')View on GitHub (pinned to 0690a5e62f)
Solutions
- If the value comes from config, make list.sort_by a plain column name: `list { sort_by :created_at }` — or a String/Symbol like 'players.name', an Array [:last_name, :first_name], or a flat Hash {players: :name} for association sorting.
- If you call abstract_model.all / the adapter yourself, pass only String, Symbol, Array of column names, or a one-level {table => column} Hash as the :sort value.
- For computed sorting (Arel/SQL expressions), pass the raw SQL string form that the String branch accepts, or wrap the call and apply reorder() yourself on the returned scope.
- If the sort value can be user-supplied, validate its class before it reaches the adapter (see defense) instead of letting ArgumentError surface as a 500.
Example fix
# before (raises ArgumentError: Unsupported sort value)
RailsAdmin.config do |config|
config.model Player do
list { sort_by 123 }
end
end
abstract_model.all(sort: Player.arel_table[:name].asc)
# after
RailsAdmin.config do |config|
config.model Player do
list { sort_by :created_at } # String, Symbol, Array, or {table: :column} Hash
end
end
abstract_model.all(sort: 'players.name') Defensive patterns
Strategy: type-guard
Validate before calling
# Before calling the adapter / building list options
sort = options[:sort]
unless sort.nil? || [String, Symbol, Array, Hash].any? { |k| sort.is_a?(k) }
raise ArgumentError, "options[:sort] must be String/Symbol/Array/Hash, got #{sort.class}"
end
# also reject nested hashes: only {table => column} one level deep is valid
options[:sort] = nil if sort.is_a?(Hash) && sort.values.any? { |v| v.is_a?(Hash) } Type guard
# Ruby type guard mirroring sort_scope's case statement (active_record.rb:162)
valid_sort_value = lambda do |v|
v.is_a?(String) || v.is_a?(Symbol) ||
(v.is_a?(Array) && v.all? { |c| c.is_a?(String) || c.is_a?(Symbol) }) ||
(v.is_a?(Hash) && v.values.all? { |c| c.is_a?(String) || c.is_a?(Symbol) })
end
valid_sort_value.call(options[:sort]) # => true/false Try / catch
begin
scope = abstract_model.all(sort: requested_sort, sort_reverse: params[:sort_reverse])
rescue ArgumentError => e
Rails.logger.warn("RailsAdmin sort rejected (#{e.message}); falling back to unsorted scope")
scope = abstract_model.all # retry without sort rather than 500ing the index page
end Prevention
- Keep list.sort_by to a literal column name (Symbol/String) in config; never assign computed objects or Integers.
- If you call abstract_model.all directly, treat its options hash as a typed API — only String/Symbol/Array/{table=>column} Hash for :sort.
- Add a one-line spec per model asserting model_config.list.sort_by is one of the supported classes, so a bad config fails in CI not production.
- Cover admin index pages with a request spec that toggles params[:sort] to catch sorting regressions before deploy.
When it happens
Trigger: Calling AbstractModel#all (or list_entries) with options[:sort] that is not String/Symbol/Array/Hash — e.g. abstract_model.all(sort: 123) or sort: User.arel_table[:name].asc (an Arel node). Or configuring `list { sort_by <non-column-object> }`, since get_sort_hash falls back to list.sort_by verbatim when params[:sort] does not match a field name. A Hash deeper than one level (nested hashes as values) also lands in the unsupported branch behavior.
Common situations: Custom code or specs that call the adapter/all API directly with an old or hand-built options hash; a model config where sort_by is assigned something other than a column name (Proc result, Integer, Arel node); upgrading an app whose sort_by was tolerated by an older adapter version; passing a nested sortable Hash instead of the flat {table => column} form.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Search operator '#{operator}' not supported
- The sort_reverse configuration option is deprecated and has
- The total_columns_width configuration option is deprecated a
- The sidescroll configuration option was removed, it is alway
- The #{option_name} configuration option is deprecated, pleas
AI-assisted analysis of railsadminteam/rails_admin@0690a5e62f (2026-08-21).
Data as JSON: /api/errors/43a32d15b1aabe22.
Report an issue: GitHub.