Shopify/liquid · error · Liquid::ArgumentError
cannot sort values of incompatible types
Error message
cannot sort values of incompatible types
What it means
`nil_safe_compare` raises Liquid::ArgumentError "cannot sort values of incompatible types" when `sort` encounters two non-nil values that cannot be compared (e.g. a String vs an Integer). Ruby's `<=>` returns nil for such pairs, and Liquid surfaces this as a clear argument error rather than an opaque comparison failure.
Solutions
- Normalize the field to one type before sorting (e.g. convert all values to strings, or all to numbers).
- Pre-process in code: coerce the collection's values to a uniform type before passing to the template.
- Use `sort_natural` if case-insensitive string comparison of stringified values is acceptable.
- Rescue Liquid::ArgumentError in the render error handler and fall back to unsorted rendering.
- Fix upstream serialization so numeric fields are always numeric (e.g. consistent JSON typing).
Example fix
// before
{{ items | sort: 'price' }}
// after
// normalize in Ruby before render: items.each { |i| i['price'] = i['price'].to_i }
{{ items | sort: 'price' }} Defensive patterns
Strategy: validation
Validate before calling
# before render
raise "mixed types in 'price'" if array.map { |i| i['price'].class }.uniq.size > 1 Type guard
def uniformly_typed?(arr, prop)
arr.map { |i| i[prop].class }.uniq.size <= 1
end Try / catch
begin template.render(assigns) rescue Liquid::ArgumentError => e render_unsorted_fallback end
Prevention
- Normalize field types before rendering (to_i/to_s consistently)
- Enforce consistent JSON serialization types upstream
- Prefer sort_natural for mixed-but-stringifyable data
- Test sort filters against data merged from multiple sources
When it happens
Trigger: `{{ array | sort: 'key' }}` or `{{ array | sort }}` where the collection (or the values at the given property) mixes types — e.g. some items have Integer prices and others String prices.
Common situations: Merged data from different sources with inconsistent field types; JSON numbers serialized as strings in some records; user-supplied input bound into the array; nil coexisting with mixed typed values after record updates.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- e.message (re-raised as Liquid::ArgumentError from…
- errors.argument.include
- Expected Hash or Liquid::Context as parameter
- cannot select the property '#
- invalid integer
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/a58ac6bbd60da452.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/standardfilters.rb:1044
raise Liquid::ArgumentError, "cannot select the property '#{Utils.to_s(property)}'"
end
def apply_operation(input, operand, operation)
result = Utils.to_number(input).send(operation, Utils.to_number(operand))
result.is_a?(BigDecimal) ? result.to_f : result
end
def nil_safe_compare(a, b)
result = a <=> b
if result
result
elsif a.nil?
1
elsif b.nil?
-1
else
raise Liquid::ArgumentError, "cannot sort values of incompatible types"
end
end
def nil_safe_casecmp(a, b)
if !a.nil? && !b.nil?
a.to_s.casecmp(b.to_s)
elsif a.nil? && b.nil?
0
else
a.nil? ? 1 : -1
end
end
class InputIterator
include Enumerable
def initialize(input, context)
@context = contextView on GitHub (pinned to 807d45a6b3)