{"record":{"id":"890e05ff1661eda0","repo":"apache/seatunnel","slug":"write-failed-890e05","errorCode":"WRITE_FAILED","errorMessage":"Row key cannot be empty. Check rowkey_column configuration.","messagePattern":"Row key cannot be empty\\. Check rowkey_column configuration\\.","errorType":"error_code","errorClass":"BigtableConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-google-bigtable/src/main/java/org/apache/seatunnel/connectors/seatunnel/bigtable/sink/BigtableSinkWriter.java","lineNumber":158,"sourceCode":"            if (bigtableClient != null) {\n                bigtableClient.close();\n            }\n        }\n    }\n\n    private void flush() {\n        if (buffer.isEmpty()) {\n            return;\n        }\n        List<RowKeyMutation> toFlush = new ArrayList<>(buffer);\n        buffer.clear(); // clear first: prevents re-sending if bulkMutate throws\n        bigtableClient.bulkMutate(toFlush);\n    }\n\n    private RowKeyMutation convertRowToMutation(SeaTunnelRow row) {\n        ByteString rowKey = buildRowKey(row);\n        if (rowKey.isEmpty()) {\n            throw new BigtableConnectorException(\n                    BigtableConnectorErrorCode.WRITE_FAILED,\n                    \"Row key cannot be empty. Check rowkey_column configuration.\");\n        }\n\n        long timestamp = System.currentTimeMillis() * 1000L; // Bigtable uses microseconds\n        if (versionColumnIndex != -1) {\n            Object versionField = row.getField(versionColumnIndex);\n            if (versionField instanceof Long) {\n                timestamp = (Long) versionField;\n            }\n        }\n\n        Mutation mutation = Mutation.create();\n\n        List<Integer> writeColumnIndexes =\n                IntStream.range(0, row.getArity())\n                        .boxed()\n                        .filter(idx -> !rowkeyColumnIndexes.contains(idx))","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-google-bigtable/src/main/java/org/apache/seatunnel/connectors/seatunnel/bigtable/sink/BigtableSinkWriter.java#L140-L176","documentation":"BigtableSinkWriter.convertRowToMutation() builds the row key from the configured rowkey_column and refuses to emit a mutation when the resulting ByteString is empty. Bigtable requires a non-empty row key for every mutation, so an empty key indicates a configuration or data problem rather than a writable row.","triggerScenarios":"A SeaTunnelRow reaches the writer where buildRowKey(row) produces an empty ByteString — e.g. rowkey_column points to a null/empty field, or the rowkey expression evaluates to nothing for that row.","commonSituations":"rowkey_column referencing a nullable source column that is null in some rows; a missing or mistyped rowkey_column config key so the key expression resolves to empty; source data with empty string keys.","solutions":["Fix the rowkey_column configuration so it references a non-nullable, always-populated column.","Filter out or coalesce rows with null/empty key values upstream (e.g. a Filter or SQL transform) before the sink.","Use a composite or derived rowkey expression that guarantees non-empty output (e.g. concatenate with a constant)."],"exampleFix":"// before\nrowkey_column = \"optional_id\"\n// after\nrowkey_column = \"id\" // or a transform: id = coalesce(optional_id, default_id)","handlingStrategy":"validation","validationCode":"// before writing, per row\nObject keyVal = row.getField(rowkeyFieldIndex);\nif (keyVal == null || keyVal.toString().isEmpty()) {\n  throw new IllegalArgumentException(\"Row key field is null/empty for row: \" + row);\n}","typeGuard":null,"tryCatchPattern":"try {\n  sink.write(row);\n} catch (BigtableConnectorException e) {\n  if (e.getMessage().contains(\"Row key cannot be empty\")) {\n    log.error(\"Skipping row with empty key: {}\", row); // or dead-letter\n  } else throw e;\n}","preventionTips":["Pick a non-nullable primary column for rowkey_column.","Add a filter transform to drop null-key rows before the sink.","Unit-test your rowkey expression against sample data including nulls."],"tags":["bigtable","sink","rowkey","write"],"backgroundTag":"empty-required-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}