alibaba/canal · error · RuntimeException

rowKey值为空

Error message

rowKey值为空

What it means

HbaseSyncService.update() computes rowKeyBytes for each updated row; if it ends up null the method throws 'rowKey值为空'. null results when the rowKey column value is null/absent, or when typeConvert returns null for a null value (no composite rowKey, and the single rowKeyColumn value is null).

Source

Thrown at client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/service/HbaseSyncService.java:207

                // 判断是否有复合主键修改
                for (String updateColumn : old.get(index).keySet()) {
                    for (String rowKeyColumnName : rowKeyColumns) {
                        if (rowKeyColumnName.equalsIgnoreCase(updateColumn)) {
                            // 调用删除插入操作
                            deleteAndInsert(config, dml);
                            continue out;
                        }
                    }
                }

                String rowKeyVale = getRowKeys(rowKeyColumns, r);
                rowKeyBytes = Bytes.toBytes(rowKeyVale);
            } else if (rowKeyColumn == null) {
                rowKeyBytes = typeConvert(null, hbaseMapping, r.values().iterator().next());
            } else {
                rowKeyBytes = getRowKeyBytes(hbaseMapping, rowKeyColumn, r);
            }
            if (rowKeyBytes == null) throw new RuntimeException("rowKey值为空");

            Map<String, MappingConfig.ColumnItem> columnItems = hbaseMapping.getColumnItems();
            HRow hRow = new HRow(rowKeyBytes);
            for (String updateColumn : old.get(index).keySet()) {
                if (hbaseMapping.getExcludeColumns() != null
                    && hbaseMapping.getExcludeColumns().contains(updateColumn)) {
                    continue;
                }
                MappingConfig.ColumnItem columnItem = columnItems.get(updateColumn);
                if (columnItem == null) {
                    String family = hbaseMapping.getFamily();
                    String qualifier = updateColumn;
                    if (hbaseMapping.isUppercaseQualifier()) {
                        qualifier = qualifier.toUpperCase();
                    }

                    Object newVal = r.get(updateColumn);

View on GitHub (pinned to 87be50e876)

Solutions

  1. Guarantee the rowKey column is non-null and unchanged-safe for UPDATEs; updates that change the rowKey are handled via deleteAndInsert, not update().
  2. Align the rowKey column name in the mapping with the DML column name exactly.
  3. Filter/cleanse null-PK updates upstream.
  4. If the PK genuinely changed, rely on the composite-rowKey path so deleteAndInsert is triggered.

Example fix

-- before: UPDATE sets rowKey col to NULL
UPDATE t SET id = NULL WHERE x=1;
-- after: keep rowKey non-null
UPDATE t SET other = 1 WHERE id = 5;
Defensive patterns

Strategy: validation

Validate before calling

// Before update sync, verify the rowKey column is present and non-null
MappingConfig.HbaseMapping m = config.getHbaseMapping();
for (Map<String,Object> r : dml.getData()) {
    String keyCol = m.getRowKey() != null
        ? m.getRowKey().split(",")[0].trim()
        : m.getRowKeyColumn().getColumn();
    if (r.get(keyCol) == null) throw new IllegalStateException("rowKey column " + keyCol + " is null in update data");
}

Try / catch

try {
    hbaseSyncService.sync(config, dml);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("rowKey")) {
        logger.error("UPDATE rowKey resolved null; check rowKey column name and null values");
    }
    throw e;
}

Prevention

When it happens

Trigger: An UPDATE DML where the rowKey column (single or composite) value resolves to null in the new data; or the mapping's rowKey column name does not match the DML column so getRowKeyBytes/getRowKeys return null.

Common situations: Updating the rowKey column itself to null (canal routes to update() when a composite key column is NOT changed); source row whose PK is null; mismatched column name casing between mapping and DML.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/659ae09ca09c7654. Report an issue: GitHub.