prestodb/presto · error · PrestoException

INVALID_ARGUMENTS

INVALID_ARGUMENTS

Error message

Type %s does not allow ordering

What it means

The less-than operator for DISTINCT types requires the distinct type to be orderable. During specialize(), Presto verifies isOrderable() on the bound DistinctType because the operator is implemented by resolving a LESS_THAN operator on the type's base type; if the base type has no ordering, resolution is impossible and INVALID_ARGUMENTS is thrown. A distinct type is assumed orderable iff its parent (base) type is orderable.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/scalar/distinct/DistinctTypeLessThanOperator.java:60

    public static final DistinctTypeLessThanOperator DISTINCT_TYPE_LESS_THAN_OPERATOR = new DistinctTypeLessThanOperator();

    private DistinctTypeLessThanOperator()
    {
        super(LESS_THAN,
                ImmutableList.of(withVariadicBound("T", DISTINCT_TYPE)),
                ImmutableList.of(),
                parseTypeSignature(BOOLEAN),
                ImmutableList.of(parseTypeSignature("T"), parseTypeSignature("T")));
    }

    @Override
    public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager)
    {
        DistinctType type = (DistinctType) boundVariables.getTypeVariable("T");
        // We assume that a distinct type is orderable iff its parent is orderable.
        // So we only check orderability of the common supertype when comparing.
        if (!type.isOrderable()) {
            throw new PrestoException(INVALID_ARGUMENTS, format("Type %s does not allow ordering", type.getDisplayName()));
        }
        Type baseType = type.getBaseType();
        FunctionHandle functionHandle = functionAndTypeManager.resolveOperator(LESS_THAN, fromTypes(baseType, baseType));

        return new BuiltInScalarFunctionImplementation(
                false,
                ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL), valueTypeArgumentProperty(RETURN_NULL_ON_NULL)),
                functionAndTypeManager.getJavaScalarFunctionImplementation(functionHandle).getMethodHandle(),
                Optional.empty());
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the distinct type's base type is orderable before using < comparisons
  2. Use equality comparison instead of ordering for non-orderable types
  3. Cast operands to an orderable type and compare those
  4. Recreate the distinct type over an orderable base type

Example fix

// before
SELECT * FROM t WHERE a < b; -- a,b are distinct type over non-orderable base
// after
SELECT * FROM t WHERE a = b; -- equality only, or cast to an orderable type
Defensive patterns

Strategy: validation

Validate before calling

if (!distinctType.isOrderable()) { throw new IllegalArgumentException("Type " + distinctType.getDisplayName() + " does not allow ordering; use equality instead"); }

Type guard

if (type instanceof DistinctType && ((DistinctType) type).isOrderable()) { /* safe to use < operator */ }

Try / catch

try { return functionAndTypeManager.resolveOperator(LESS_THAN, fromTypes(baseType, baseType)); } catch (PrestoException e) { if (INVALID_ARGUMENTS.toErrorCode().equals(e.getErrorCode())) { /* rewrite to equality or cast */ } throw e; }

Prevention

When it happens

Trigger: Calling the less_than operator with a DISTINCT type argument whose base type is not orderable; the check fails in specialize() when bound type variable 'T' has isOrderable() == false.

Common situations: Comparing distinct-typed columns with < in WHERE clauses, JOIN conditions, or ORDER BY where the distinct type was declared over a non-orderable base type.

Related errors


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