apache/seatunnel · error · SeaTunnelException
Incremental snapshot for tables requires primary key, but ta
Error message
Incremental snapshot for tables requires primary key, but table ${table.id()} doesn't have primary key. What it means
PostgresUtils.getSplitType converts the table's primary key columns into the split key type used by the incremental snapshot framework. Incremental snapshots chop tables into chunks by a key column, so if table.primaryKeyColumns() is empty it throws SeaTunnelException stating the table must have a primary key.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/utils/PostgresUtils.java:265
chunkSize);
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<?>[] {PostgresTypeUtils.convertFromColumn(splitColumn)});
}
public static Offset getLsnPosition(SourceRecord record) {
return getLsnPosition(record.sourceOffset());View on GitHub (pinned to cf67b549a7)
Solutions
- Add a primary key to the table: ALTER TABLE <t> ADD PRIMARY KEY (<cols>)
- Choose an existing NOT NULL UNIQUE column as the effective key if a PK cannot be added
- Disable incremental snapshot (scan.incremental.snapshot.enabled=false) to fall back to the lock-based snapshot mode, if supported for your version
- Verify the connector's schema read can see the constraint (privileges/catalog visibility)
Example fix
// before CREATE TABLE users (id bigint, name text); // after ALTER TABLE users ADD PRIMARY KEY (id);
Defensive patterns
Strategy: validation
Validate before calling
SELECT a.attname FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) WHERE i.indrelid = 'public.orders'::regclass AND i.indisprimary;
Prevention
- Always define a PRIMARY KEY on CDC tables
- Do not drop PKs for bulk loads on replicated tables
- Fall back to non-incremental snapshot mode only when the table truly has no key
When it happens
Trigger: Enabling incremental snapshot (scan.incremental.snapshot.enabled=true, the default) on a Postgres table defined without a PRIMARY KEY constraint, or where the PK is not visible to the schema reader (e.g. PK excluded from publication/schema read).
Common situations: Legacy Postgres tables created without PKs; tables whose PK was dropped for bulk-load performance; partitioned tables where the PK lives on partitions; readers with insufficient privilege to see constraints.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
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
- Exactly once is enabled, but not found primary key or unique
- Primary key(%s) is not in table(%s) columns(%s)
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/29ddace1cda95df9.
Report an issue: GitHub.