{"record":{"id":"659ae09ca09c7654","repo":"alibaba/canal","slug":"rowkey-659ae0","errorCode":null,"errorMessage":"rowKey值为空","messagePattern":"rowKey值为空","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/service/HbaseSyncService.java","lineNumber":207,"sourceCode":"                // 判断是否有复合主键修改\n                for (String updateColumn : old.get(index).keySet()) {\n                    for (String rowKeyColumnName : rowKeyColumns) {\n                        if (rowKeyColumnName.equalsIgnoreCase(updateColumn)) {\n                            // 调用删除插入操作\n                            deleteAndInsert(config, dml);\n                            continue out;\n                        }\n                    }\n                }\n\n                String rowKeyVale = getRowKeys(rowKeyColumns, r);\n                rowKeyBytes = Bytes.toBytes(rowKeyVale);\n            } else if (rowKeyColumn == null) {\n                rowKeyBytes = typeConvert(null, hbaseMapping, r.values().iterator().next());\n            } else {\n                rowKeyBytes = getRowKeyBytes(hbaseMapping, rowKeyColumn, r);\n            }\n            if (rowKeyBytes == null) throw new RuntimeException(\"rowKey值为空\");\n\n            Map<String, MappingConfig.ColumnItem> columnItems = hbaseMapping.getColumnItems();\n            HRow hRow = new HRow(rowKeyBytes);\n            for (String updateColumn : old.get(index).keySet()) {\n                if (hbaseMapping.getExcludeColumns() != null\n                    && hbaseMapping.getExcludeColumns().contains(updateColumn)) {\n                    continue;\n                }\n                MappingConfig.ColumnItem columnItem = columnItems.get(updateColumn);\n                if (columnItem == null) {\n                    String family = hbaseMapping.getFamily();\n                    String qualifier = updateColumn;\n                    if (hbaseMapping.isUppercaseQualifier()) {\n                        qualifier = qualifier.toUpperCase();\n                    }\n\n                    Object newVal = r.get(updateColumn);\n","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/service/HbaseSyncService.java#L189-L225","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Guarantee the rowKey column is non-null and unchanged-safe for UPDATEs; updates that change the rowKey are handled via deleteAndInsert, not update().","Align the rowKey column name in the mapping with the DML column name exactly.","Filter/cleanse null-PK updates upstream.","If the PK genuinely changed, rely on the composite-rowKey path so deleteAndInsert is triggered."],"exampleFix":"-- before: UPDATE sets rowKey col to NULL\nUPDATE t SET id = NULL WHERE x=1;\n-- after: keep rowKey non-null\nUPDATE t SET other = 1 WHERE id = 5;","handlingStrategy":"validation","validationCode":"// Before update sync, verify the rowKey column is present and non-null\nMappingConfig.HbaseMapping m = config.getHbaseMapping();\nfor (Map<String,Object> r : dml.getData()) {\n    String keyCol = m.getRowKey() != null\n        ? m.getRowKey().split(\",\")[0].trim()\n        : m.getRowKeyColumn().getColumn();\n    if (r.get(keyCol) == null) throw new IllegalStateException(\"rowKey column \" + keyCol + \" is null in update data\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    hbaseSyncService.sync(config, dml);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"rowKey\")) {\n        logger.error(\"UPDATE rowKey resolved null; check rowKey column name and null values\");\n    }\n    throw e;\n}","preventionTips":["Never update the single rowKey column to null (use composite rowKey + deleteAndInsert for key changes).","Match rowKey column names exactly to DML column names.","Filter null-PK update events upstream."],"tags":["hbase-adapter","sync","rowkey","update"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}