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

  1. Rewrite the lambda to use Integer.compare/Long.compare instead of subtraction to avoid overflow
  2. Ensure the comparator returns 0 only for equal elements and opposite signs for swapped arguments
  3. Make the comparator deterministic (no dependence on mutable/external state)
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/ad11d2ed56842763. Report an issue: GitHub.