apache/seatunnel · error · SeaTunnelException

The non-primary key field cannot be empty. Please set other…

Error message

The non-primary key field cannot be empty. Please set other fields

What it means

Thrown by XuguDialect.getUpsertStatement when building an upsert (MERGE) statement finds that all fields are primary key fields, leaving no non-key fields to update. Xugu upserts require at least one column that is not part of the primary key.

Solutions

  1. Include at least one non-primary-key column in the sink table and schema
  2. If you only need key-based inserts, switch the sink to insert mode instead of upsert
  3. Reduce the primary key definition on the target table so some columns become non-key fields
  4. Set the sink primary key configuration correctly so it does not span all fields

Example fix

// before: fields=[id], pk=[id] -> throws
// after
// table: CREATE TABLE t (id INT PRIMARY KEY, val VARCHAR(64));
// fields=[id, val], pk=[id]
Defensive patterns

Strategy: validation

Validate before calling

// Before running an upsert sink on Xugu
if (Arrays.asList(pkNames).containsAll(Arrays.asList(fieldNames))) {
    throw new IllegalArgumentException("Need at least one non-primary-key field for upsert");
}

Prevention

When it happens

Trigger: Configuring a Xugu sink with a primary key where the sink's field list equals the primary key list exactly (no additional payload columns), so no UPDATE assignment can be generated.

Common situations: Sink table defined with all columns in the primary key; user forgot to include non-key columns in the sink schema; trying to do pure key-only writes with upsert mode enabled instead of append/insert mode.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/xugu/XuguDialect.java:107

    @Override
    public TablePath parse(String tablePath) {
        return TablePath.of(tablePath, true);
    }

    @Override
    public String tableIdentifier(TablePath tablePath) {
        return quoteIdentifier(tablePath.getSchemaAndTableName());
    }

    @Override
    public Optional<String> getUpsertStatement(
            String database, String tableName, String[] fieldNames, String[] pkNames) {
        List<String> nonUniqueKeyFields =
                Arrays.stream(fieldNames)
                        .filter(fieldName -> !Arrays.asList(pkNames).contains(fieldName))
                        .collect(Collectors.toList());
        if (nonUniqueKeyFields.isEmpty()) {
            throw new SeaTunnelException(
                    "The non-primary key field cannot be empty. Please set other fields");
        }
        String valuesBinding =
                Arrays.stream(fieldNames)
                        .map(fieldName -> ":" + fieldName + " " + quoteIdentifier(fieldName))
                        .collect(Collectors.joining(", "));

        String usingClause = String.format("SELECT %s FROM DUAL", valuesBinding);
        String onConditions =
                Arrays.stream(pkNames)
                        .map(
                                fieldName ->
                                        String.format(
                                                "TARGET.%s=SOURCE.%s",
                                                quoteIdentifier(fieldName),
                                                quoteIdentifier(fieldName)))
                        .collect(Collectors.joining(" AND "));
        String updateSetClause =

View on GitHub (pinned to cf67b549a7)