mongodb/mongoid · error · Mongoid::Errors::InvalidQuery
Expression must be a Hash: #
Error message
Expression must be a Hash: #{Errors::InvalidQuery.truncate_expr(criterion)} What it means
Raised by Selectable#expr_query when the expression argument is not a Hash. expr_query builds a raw MongoDB query expression and requires field/value pairs; the faulting input is the non-Hash criterion (truncated in the message).
Solutions
- Pass a Hash such as { age: 50 } to expr_query
- Build operator conditions as hashes, e.g. { field: { '$gt' => 1 } }
Defensive patterns
Strategy: type-guard
When it happens
Trigger: Thrown at lib/mongoid/criteria/queryable/selectable.rb:813 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of mongodb/mongoid@0da0e23d71 (2026-08-23).
Data as JSON: /api/errors/aebd8b3fe9bfcdad.
Report an issue: GitHub.
Appendix: source
Thrown at lib/mongoid/criteria/queryable/selectable.rb:813
#
# @example Create the selection.
# selectable.expr_query(age: 50)
#
# @param [ Hash ] criterion The field/value pairs.
#
# @return [ Selectable ] The cloned selectable.
# @api private
# Operators permitted in a query expression without opt-in.
# Excludes $where (JS execution) and other operators not needed for
# ordinary application queries.
ALLOWED_QUERY_OPERATORS = %w[
$and $or $nor $not $text $comment $expr $jsonSchema $alwaysFalse $alwaysTrue
].freeze
def expr_query(criterion)
raise ArgumentError, 'Criterion cannot be nil here' if criterion.nil?
unless criterion.is_a?(Hash)
raise Errors::InvalidQuery, "Expression must be a Hash: #{Errors::InvalidQuery.truncate_expr(criterion)}"
end
normalized = _mongoid_expand_keys(criterion)
clone.tap do |query|
normalized.each do |field, value|
field_s = field.to_s
if field_s.start_with?('$')
unless Mongoid.allow_unsafe_query_operators? || ALLOWED_QUERY_OPERATORS.include?(field_s)
raise Errors::InvalidQuery,
"Operator '#{field_s}' is not allowed in a query expression. " \
'Set Mongoid.allow_unsafe_query_operators = true to permit all operators.'
end
query.add_operator_expression(field_s, value)
else
query.add_field_expression(field, value)
end
end
query.reset_strategies!View on GitHub (pinned to 0da0e23d71)