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

Incremental snapshot chunking requires a primary key to split the table. Db2Utils.getSplitType inspects the Debezium Table's primary-key columns and throws SeaTunnelException when the table has none, refusing to snapshot a key-less table.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-db2/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/db2/utils/Db2Utils.java:242

                        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<?>[] {Db2TypeUtils.convertFromColumn(splitColumn)});
    }

    public static Offset getLsn(SourceRecord record) {
        return getLsnPosition(record.sourceOffset());

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Add a primary key (or a NOT NULL unique key recognized as PK) to the table
  2. Disable incremental snapshot so the table is read by the legacy snapshot mechanism
  3. Choose a table that has a primary key
  4. Verify the schema/table resolution picks the intended table that does have a PK

Example fix

// before
ALTER TABLE MYSCHEMA.MYTABLE ...; -- no PK
// after
ALTER TABLE MYSCHEMA.MYTABLE ADD PRIMARY KEY (ID);
Defensive patterns

Strategy: validation

Validate before calling

// Verify PK before enabling incremental snapshot
SELECT KC.NAME FROM SYSCAT.KEYCOLUSE KC JOIN SYSCAT.TABCONST TC ON KC.CONSTNAME = TC.CONSTNAME AND KC.TABSCHEMA = TC.TABSCHEMA AND KC.TABNAME = TC.TABNAME WHERE TC.TYPE = 'P' AND TC.TABSCHEMA='MYSCHEMA' AND TC.TABNAME='MYTABLE';

Prevention

When it happens

Trigger: Enabling incremental snapshot (scan.incremental.snapshot.enabled=true or default in newer versions) on a DB2 table with no primary key defined in its schema metadata.

Common situations: Legacy DB2 tables created without PK; keys exist physically but are not declared in DDL so schema metadata sees none; connector reads the wrong schema/database so the PK isn't picked up.

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/7c50f15db07f3d4b. Report an issue: GitHub.