prestodb/presto · error · PrestoException
INVALID_FUNCTION_ARGUMENT
INVALID_FUNCTION_ARGUMENT
Error message
Lambda comparator violates the comparator contract
What it means
array_sort with a lambda comparator requires the comparator to satisfy the java.util.Comparator contract (antisymmetry, transitivity, consistency). When List.sort detects a contract violation it throws IllegalArgumentException, which Presto rethrows as INVALID_FUNCTION_ARGUMENT.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/scalar/ArraySortComparatorFunction.java:163
private void initPositionsList(int arrayLength)
{
if (positions.size() < arrayLength) {
positions = Ints.asList(new int[arrayLength]);
}
for (int i = 0; i < arrayLength; i++) {
positions.set(i, i);
}
}
private void sortPositions(int arrayLength, Comparator<Integer> comparator)
{
List<Integer> list = positions.subList(0, arrayLength);
try {
list.sort(comparator);
}
catch (IllegalArgumentException e) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Lambda comparator violates the comparator contract", e);
}
}
private Block computeResultBlock(Type type, Block block, int arrayLength)
{
BlockBuilder blockBuilder = type.createBlockBuilder(null, arrayLength);
for (int i = 0; i < arrayLength; ++i) {
type.appendTo(block, positions.get(i), blockBuilder);
}
return blockBuilder.build();
}
private static int comparatorResult(Long result)
{
checkCondition(
(result != null) && ((result == -1) || (result == 0) || (result == 1)),View on GitHub (pinned to 55bb57d202)
Solutions
- Rewrite the lambda to use Integer.compare/Long.compare instead of subtraction to avoid overflow
- Ensure the comparator returns 0 only for equal elements and opposite signs for swapped arguments
- Make the comparator deterministic (no dependence on mutable/external state)
- Test the comparator on representative data before running on large arrays
Example fix
// before sort(arr, (a, b) -> a - b) // after sort(arr, (a, b) -> Integer.compare(a, b))
Defensive patterns
Strategy: validation
Validate before calling
-- test comparator determinism on sample data SELECT sort(sample_arr, (a, b) -> Integer.compare(a, b)) FROM t LIMIT 100;
Try / catch
try(sort(arr, (a, b) -> a - b)) -- returns NULL on contract violation; better: fix comparator with compare()
Prevention
- Always use Integer.compare/Long.compare/Double.compare, never subtraction, in lambdas
- Ensure comparator returns opposite signs for swapped args and 0 only for equals
- Avoid NULL-unsafe expressions inside comparators; handle NULL explicitly
- Unit-test comparators with edge values (MIN/MAX, equal elements)
When it happens
Trigger: Calling sort(array, (a, b) -> comparatorLambda) where the lambda returns inconsistent signs, e.g. returns 0 for unequal elements, reverses sign non-symmetrically, or uses arithmetic that overflows (like (int)(a-b) on large values).
Common situations: Comparator written as (a,b) -> a - b causing integer overflow on large values; comparators referencing non-deterministic data; NULL handling that flips ordering between comparisons.
Related errors
- INVALID_FUNCTION_ARGUMENT
- INVALID_TABLE_PROPERTY
- Invalid time from server:
- Expected column to be a time type but is
- Invalid timestamp from server:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/ad11d2ed56842763.
Report an issue: GitHub.