apache/seatunnel · error · SeaTunnelException
Incremental snapshot for tables requires primary key, but ta
Error message
Incremental snapshot for tables requires primary key, but table %s doesn't have primary key.
What it means
SqlServerUtils.getSplitType derives the chunk-split key from the table's primary key; if the table has no primary key columns, incremental snapshot cannot chunk it, so it throws SeaTunnelException naming the table. This is a fail-fast validation at job startup.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/sqlserver/utils/SqlServerUtils.java:247
quotedColumn);
return jdbc.prepareQueryAndMap(
query,
ps -> ps.setObject(1, includedLowerBound),
rs -> {
if (!rs.next()) {
// this should never happen
throw new SQLException(
String.format(
"No result returned after running query [%s]", query));
}
return rs.getObject(1);
});
}
public static SeaTunnelRowType getSplitType(Table table) {
List<Column> primaryKeys = table.primaryKeyColumns();
if (primaryKeys.isEmpty()) {
throw new SeaTunnelException(
String.format(
"Incremental snapshot for tables requires primary key,"
+ " but table %s doesn't have primary key.",
table.id()));
}
// use first field in primary key as the split key
return getSplitType(primaryKeys.get(0));
}
public static SeaTunnelRowType getSplitType(Column splitColumn) {
return new SeaTunnelRowType(
new String[] {splitColumn.name()},
new SeaTunnelDataType<?>[] {SqlServerTypeUtils.convertFromColumn(splitColumn)});
}
public static Offset getLsn(SourceRecord record) {
return getLsnPosition(record.sourceOffset());View on GitHub (pinned to cf67b549a7)
Solutions
- Add a primary key (or a NOT NULL unique index the connector recognizes) to the table
- If DDL is not possible, use a snapshot-only read mode instead of incremental snapshot
- Exclude the keyless table from table-names and capture it via a different mechanism
- Ensure the PK exists in the same database the connector reads (not just a logical replica)
Example fix
// before table-names = ["dbo.Events"] // no primary key -> fails // after (SQL Server) ALTER TABLE dbo.Events ADD CONSTRAINT PK_Events PRIMARY KEY (EventId);
Defensive patterns
Strategy: validation
Validate before calling
-- Fail fast before submitting the job
IF NOT EXISTS (
SELECT 1 FROM sys.key_constraints
WHERE type = 'PK' AND parent_object_id = OBJECT_ID('dbo.Events'))
THROW 50000, 'Table dbo.Events has no primary key', 1; Type guard
// Java pre-check mirroring the connector's validation
static void requirePrimaryKey(Table table) {
if (table.primaryKeyColumns().isEmpty()) {
throw new IllegalArgumentException(
"Table " + table.id() + " needs a primary key for incremental snapshot");
}
} Prevention
- Audit all tables in table-names for PRIMARY KEY constraints before enabling incremental snapshot
- Add PKs (or NOT NULL unique indexes) to keyless tables
- Use snapshot-only mode for tables that cannot have keys
- Exclude keyless tables from incremental capture
When it happens
Trigger: getSplitType called during incremental-snapshot setup for a table whose Table.primaryKeyColumns() is empty — a heap table or table without a PK/unique key in SQL Server.
Common situations: Capturing a SQL Server table created without a PRIMARY KEY constraint; capturing a view or heap table; partitioned tables where the PK doesn't cover all columns; older databases migrated without constraints.
Related errors
- Incremental snapshot for tables requires primary key, but ta
- Incremental snapshot for tables requires primary key, but ta
- Incremental snapshot for tables requires primary key, but ta
- Streaming mode requires a Primary Key in the schema of table
- Exactly once is enabled, but not found primary key or unique
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/2e8541dc4c462436.
Report an issue: GitHub.