prestodb/presto · error · PrestoException
INVALID_FUNCTION_ARGUMENT
INVALID_FUNCTION_ARGUMENT
Error message
zorder function requires a ROW type
What it means
The zorder() SQL function computes a Z-order key from a ROW-typed argument. If the resolved type T is not a RowType (e.g. a scalar was passed or the binding produced a non-row type), it throws INVALID_FUNCTION_ARGUMENT since Z-ordering requires multiple named fields to interleave.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/function/IcebergZOrderFunctions.java:136
return ZOrderByteUtils.longToOrderedBytes(value);
}
/**
* Computes Z-order value from a ROW of columns.
* Usage: zorder(ROW(col1, col2, col3, ...))
*
* @param rowType The type information for the row
* @param rowBlock The row block containing the column values
* @return The interleaved Z-order binary value
*/
@ScalarFunction("zorder")
@TypeParameter("T")
@SqlType(StandardTypes.VARBINARY)
@SqlNullable
public static Slice zorder(@TypeParameter("T") Type rowType, @SqlType("T") Block rowBlock)
{
if (!(rowType instanceof RowType)) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "zorder function requires a ROW type");
}
RowType row = (RowType) rowType;
List<RowType.Field> fields = row.getFields();
int fieldCount = fields.size();
if (fieldCount == 0) {
return Slices.wrappedBuffer(new byte[0]);
}
// Convert each field to ordered bytes based on its type
Slice[] columnBytes = new Slice[fieldCount];
int totalSize = 0;
for (int i = 0; i < fieldCount; i++) {
Type fieldType = fields.get(i).getType();
if (rowBlock.isNull(i)) {View on GitHub (pinned to 55bb57d202)
Solutions
- Wrap the arguments in a row: zorder(CAST(ROW(a, b) AS ROW(x <type>, y <type>))).
- Verify the column used in zorder is declared as a ROW type in the table schema.
- Check function binding — ensure the @TypeParameter T is bound to a row type, not a scalar.
Example fix
// before SELECT zorder(x, y) FROM t; // after SELECT zorder(CAST(ROW(x, y) AS ROW(a double, b double))) FROM t;
Defensive patterns
Strategy: type-guard
Validate before calling
boolean rowTyped(Type t) { return t instanceof RowType; }
// SQL-side check before clustering: DESCRIBE table; ensure column is row(...) Type guard
boolean isRowTyped(Type t) {
return t instanceof RowType;
} Try / catch
try { result = session.getMetadata().getFunctionRegistry()...zorder(...); } catch (PrestoException e) { if (e.getErrorCode() == INVALID_FUNCTION_ARGUMENT.toErrorCode()) { /* wrap args in ROW(...) */ } throw e; } Prevention
- Always pass a single row(...)-typed column to zorder
- Use CAST(ROW(a,b) AS ROW(x t1, y t2)) for multiple columns
- Verify column types with DESCRIBE before sort-order DDL
When it happens
Trigger: Calling zorder(col) where col is not a row/struct type — e.g. zorder(a, b) misuse or a bind that resolves T to a primitive instead of row(...).
Common situations: Users writing ORDER BY zorder(x, y) expecting multi-arg support; clustering DDL against tables whose column was changed from a struct to a scalar.
Related errors
- Expected all parameters to be named type, but got %s
- fieldType.getTypeSignature() + " type is not orderable"
- ROW comparison not supported for fields with null elements
- INVALID_FUNCTION_ARGUMENT
- Not a Hive table:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/b69dd9bb1ce162af.
Report an issue: GitHub.