{"record":{"id":"bd22e28720c8628a","repo":"prestodb/presto","slug":"invalid-function-argument","errorCode":"INVALID_FUNCTION_ARGUMENT","errorMessage":"Column mapped as the Accumulo row ID cannot be null","messagePattern":"Column mapped as the Accumulo row ID cannot be null","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"presto-accumulo/src/main/java/com/facebook/presto/accumulo/io/AccumuloPageSink.java","lineNumber":148,"sourceCode":"        }\n    }\n\n    /**\n     * Converts a {@link Row} to an Accumulo mutation.\n     *\n     * @param row Row object\n     * @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.\n     * @param columns All column handles for the Row, sorted by ordinal.\n     * @param serializer Instance of {@link AccumuloRowSerializer} used to encode the values of the row to the Mutation\n     * @return Mutation\n     */\n    public static Mutation toMutation(Row row, int rowIdOrdinal, List<AccumuloColumnHandle> columns, AccumuloRowSerializer serializer)\n    {\n        // Set our value to the row ID\n        Text value = new Text();\n        Field rowField = row.getField(rowIdOrdinal);\n        if (rowField.isNull()) {\n            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, \"Column mapped as the Accumulo row ID cannot be null\");\n        }\n\n        setText(rowField, value, serializer);\n\n        // Iterate through all the column handles, setting the Mutation's columns\n        Mutation mutation = new Mutation(value);\n\n        // Store row ID in a special column\n        mutation.put(ROW_ID_COLUMN, ROW_ID_COLUMN, new Value(value.copyBytes()));\n        for (AccumuloColumnHandle columnHandle : columns) {\n            // Skip the row ID ordinal\n            if (columnHandle.getOrdinal() == rowIdOrdinal) {\n                continue;\n            }\n\n            // If the value of the field is not null\n            if (!row.getField(columnHandle.getOrdinal()).isNull()) {\n                // Serialize the value to the text","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-accumulo/src/main/java/com/facebook/presto/accumulo/io/AccumuloPageSink.java#L130-L166","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the row ID column is non-NULL: fix the INSERT column list/order or the source data","Filter out rows with null keys before inserting: WHERE rowid_col IS NOT NULL","Coerce nulls to a sentinel/default value if acceptable for the application","Verify which column is the row ID (SHOW CREATE TABLE) and adjust the INSERT to supply a real value there"],"exampleFix":"// before\nINSERT INTO myschema.mytable SELECT col_a, NULL, col_b FROM staging; -- NULL lands in rowid column\n// after\nINSERT INTO myschema.mytable\nSELECT col_a, coalesce(rowid_src, 'unknown'), col_b\nFROM staging\nWHERE rowid_src IS NOT NULL;","handlingStrategy":"validation","validationCode":"// Reject inserts whose row ID column is NULL before writing\nTableMetadata tableMeta = metadata.getTableMetadata(session, tableName);\nAccumuloTableHandle table = (AccumuloTableHandle) tableMeta.getTable();\nint rowIdOrdinal = columns.stream()\n    .filter(c -> c.getName().equals(table.getRowId()))\n    .map(AccumuloColumnHandle::getOrdinal).findAny()\n    .orElseThrow(() -> new IllegalArgumentException(\"row id column missing\"));\n// per-row check before insert:\nif (page.getBlock(rowIdOrdinal).isNull(position)) {\n    throw new IllegalArgumentException(\"Row ID column \" + table.getRowId() + \" cannot be NULL\");\n}","typeGuard":"boolean hasNonNullRowId(Page page, int rowIdOrdinal) {\n    Block block = page.getBlock(rowIdOrdinal);\n    for (int pos = 0; pos < block.getPositionCount(); pos++) {\n        if (block.isNull(pos)) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    pageSink.appendPage(page);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getCode() == StandardErrorCode.INVALID_FUNCTION_ARGUMENT.toErrorCode().getCode()\n            && e.getMessage().contains(\"row ID cannot be null\")) {\n        throw new IllegalArgumentException(\"Filter out rows where \" + rowIdColumn + \" IS NULL before inserting\", e);\n    }\n    throw e;\n}","preventionTips":["Declare the row ID column NOT NULL in the table definition so nulls fail at insert analysis time","Always use an explicit column list in INSERT statements to avoid positional mismatches","Add IS NOT NULL filters when inserting from external sources with nullable keys","Run SHOW CREATE TABLE to confirm which column is the row ID before bulk loads"],"tags":["accumulo","null-value","row-id","insert"],"backgroundTag":"null-row-id-column","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}