alibaba/canal · error · RuntimeException

empty rowKey

Error message

empty rowKey

What it means

HbaseSyncService.insert() throws 'empty rowKey' after building each HRow if its rowKey is still null. This happens when hbaseMapping.getRowKey() is null (no composite key) and convertData2Row did not encounter a ROWKEY-marked column as the first entry — i.e. no column was configured as the rowKey.

Source

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

        // return;
        // }
        int i = 1;
        boolean complete = false;
        List<HRow> rows = new ArrayList<>();
        for (Map<String, Object> r : data) {
            HRow hRow = new HRow();

            // 拼接复合rowKey
            if (hbaseMapping.getRowKey() != null) {
                String[] rowKeyColumns = hbaseMapping.getRowKey().trim().split(",");
                String rowKeyVale = getRowKeys(rowKeyColumns, r);
                // params.put("rowKey", Bytes.toBytes(rowKeyVale));
                hRow.setRowKey(Bytes.toBytes(rowKeyVale));
            }

            convertData2Row(hbaseMapping, hRow, r);
            if (hRow.getRowKey() == null) {
                throw new RuntimeException("empty rowKey");
            }
            rows.add(hRow);
            complete = false;
            if (i % config.getHbaseMapping().getCommitBatch() == 0 && !rows.isEmpty()) {
                hbaseTemplate.puts(hbaseMapping.getHbaseTable(), rows);
                rows.clear();
                complete = true;
            }
            i++;
        }
        if (!complete && !rows.isEmpty()) {
            hbaseTemplate.puts(hbaseMapping.getHbaseTable(), rows);
        }

    }

    /**
     * 将Map数据转换为HRow行数据

View on GitHub (pinned to 87be50e876)

Solutions

  1. Configure a rowKey: either set 'rowKey: <col>' (composite) or mark exactly one column value as 'ROWKEY' in the columns map.
  2. Confirm the rowKey column name matches the column name in the incoming DML data exactly (case-sensitive).
  3. Ensure the rowKey column value is non-null in the data.
  4. Re-validate the mapping config.

Example fix

# before (no rowKey)
hbaseMapping:
  columns:
    id: CF:id

# after
hbaseMapping:
  columns:
    id: ROWKEY
    name: CF:name
Defensive patterns

Strategy: validation

Validate before calling

// Verify a rowKey strategy is configured before sync
MappingConfig.HbaseMapping m = config.getHbaseMapping();
boolean hasKey = m.getRowKey() != null || m.getRowKeyColumn() != null;
if (!hasKey) {
    throw new IllegalStateException("HBase mapping needs a rowKey or a ROWKEY column");
}

Try / catch

try {
    hbaseSyncService.sync(config, dml);
} catch (RuntimeException e) {
    if ("empty rowKey".equals(e.getMessage())) {
        logger.error("INSERT could not build a rowKey; configure rowKey/ROWKEY and check column names");
    }
    throw e;
}

Prevention

When it happens

Trigger: An INSERT DML is synced for an HBase mapping that has neither a composite 'rowKey:' nor any column marked ROWKEY, so the row never receives a key.

Common situations: Mapping YAML with a 'columns:' map but no rowKey/ROWKEY designation; the rowKey column name in the mapping does not match the actual synced column name.

Related errors


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