prestodb/presto · error

INVALID_FUNCTION_ARGUMENT

INVALID_FUNCTION_ARGUMENT

Error message

Column mapped as the Accumulo row ID cannot be null

What it means

Thrown in AccumuloPageSink.toMutation when the row value at the rowIdOrdinal is null. The Accumulo row ID is the mutation's unique row key — Accumulo mutations cannot have a null row — so the Presto Accumulo connector rejects the row with INVALID_FUNCTION_ARGUMENT instead of writing an unusable mutation.

Source

Thrown at presto-accumulo/src/main/java/com/facebook/presto/accumulo/io/AccumuloPageSink.java:148

        }
    }

    /**
     * Converts a {@link Row} to an Accumulo mutation.
     *
     * @param row Row object
     * @param rowIdOrdinal Ordinal in the list of columns that is the row ID. This isn't checked at all, so I hope you're right. Also, it is expected that the list of column handles is sorted in ordinal order. This is a very demanding function.
     * @param columns All column handles for the Row, sorted by ordinal.
     * @param serializer Instance of {@link AccumuloRowSerializer} used to encode the values of the row to the Mutation
     * @return Mutation
     */
    public static Mutation toMutation(Row row, int rowIdOrdinal, List<AccumuloColumnHandle> columns, AccumuloRowSerializer serializer)
    {
        // Set our value to the row ID
        Text value = new Text();
        Field rowField = row.getField(rowIdOrdinal);
        if (rowField.isNull()) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Column mapped as the Accumulo row ID cannot be null");
        }

        setText(rowField, value, serializer);

        // Iterate through all the column handles, setting the Mutation's columns
        Mutation mutation = new Mutation(value);

        // Store row ID in a special column
        mutation.put(ROW_ID_COLUMN, ROW_ID_COLUMN, new Value(value.copyBytes()));
        for (AccumuloColumnHandle columnHandle : columns) {
            // Skip the row ID ordinal
            if (columnHandle.getOrdinal() == rowIdOrdinal) {
                continue;
            }

            // If the value of the field is not null
            if (!row.getField(columnHandle.getOrdinal()).isNull()) {
                // Serialize the value to the text

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the row ID column is non-NULL: fix the INSERT column list/order or the source data
  2. Filter out rows with null keys before inserting: WHERE rowid_col IS NOT NULL
  3. Coerce nulls to a sentinel/default value if acceptable for the application
  4. Verify which column is the row ID (SHOW CREATE TABLE) and adjust the INSERT to supply a real value there

Example fix

// before
INSERT INTO myschema.mytable SELECT col_a, NULL, col_b FROM staging; -- NULL lands in rowid column
// after
INSERT INTO myschema.mytable
SELECT col_a, coalesce(rowid_src, 'unknown'), col_b
FROM staging
WHERE rowid_src IS NOT NULL;
Defensive patterns

Strategy: validation

Validate before calling

// Reject inserts whose row ID column is NULL before writing
TableMetadata tableMeta = metadata.getTableMetadata(session, tableName);
AccumuloTableHandle table = (AccumuloTableHandle) tableMeta.getTable();
int rowIdOrdinal = columns.stream()
    .filter(c -> c.getName().equals(table.getRowId()))
    .map(AccumuloColumnHandle::getOrdinal).findAny()
    .orElseThrow(() -> new IllegalArgumentException("row id column missing"));
// per-row check before insert:
if (page.getBlock(rowIdOrdinal).isNull(position)) {
    throw new IllegalArgumentException("Row ID column " + table.getRowId() + " cannot be NULL");
}

Type guard

boolean hasNonNullRowId(Page page, int rowIdOrdinal) {
    Block block = page.getBlock(rowIdOrdinal);
    for (int pos = 0; pos < block.getPositionCount(); pos++) {
        if (block.isNull(pos)) return false;
    }
    return true;
}

Try / catch

try {
    pageSink.appendPage(page);
} catch (PrestoException e) {
    if (e.getErrorCode().getCode() == StandardErrorCode.INVALID_FUNCTION_ARGUMENT.toErrorCode().getCode()
            && e.getMessage().contains("row ID cannot be null")) {
        throw new IllegalArgumentException("Filter out rows where " + rowIdColumn + " IS NULL before inserting", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Inserting a row whose column mapped as the Accumulo row ID (table's row_id property) is NULL; commonly via INSERT INTO ... VALUES with a NULL in that position, or data from a source table containing nulls in the row ID column.

Common situations: INSERT with column order mismatch so NULL lands in the row ID column; migrating data from a relational source that permits null keys; CTAS/INSERT from an external feed with missing key values; confusion about which column the connector treats as the row ID.

Related errors


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