apache/seatunnel · error · PaimonConnectorException

NON_PRIMARY_KEY_CHECK_ERROR

NON_PRIMARY_KEY_CHECK_ERROR

Error message

 `%s` will is empty when `%s`is true, but is %s

What it means

PaimonSinkConfig validates the sink's primary key configuration. When the `non_primary_key` option is set to true, the `primary_keys` option must be left empty; if primary keys are still configured, the connector throws NON_PRIMARY_KEY_CHECK_ERROR because the two options are contradictory.

Source

Thrown at seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/config/PaimonSinkConfig.java:71

     * SaveMode auto-create options from {@code table_options}. Applied only when building the
     * Paimon schema for table creation; not merged into runtime {@link #writeProps}.
     */
    private final Map<String, String> tableOptions;

    public PaimonSinkConfig(ReadonlyConfig readonlyConfig) {
        super(readonlyConfig);
        this.schemaSaveMode = readonlyConfig.get(PaimonSinkOptions.SCHEMA_SAVE_MODE);
        this.dataSaveMode = readonlyConfig.get(PaimonSinkOptions.DATA_SAVE_MODE);
        this.nonPrimaryKey = readonlyConfig.get(PaimonSinkOptions.NON_PRIMARY_KEY);
        this.primaryKeys = stringToList(readonlyConfig.get(PaimonSinkOptions.PRIMARY_KEYS), ",");
        if (this.nonPrimaryKey && !this.primaryKeys.isEmpty()) {
            String message =
                    String.format(
                            " `%s` will is empty when `%s`is true, but is %s",
                            PaimonSinkOptions.PRIMARY_KEYS.key(),
                            PaimonSinkOptions.NON_PRIMARY_KEY.key(),
                            this.primaryKeys);
            throw new PaimonConnectorException(
                    PaimonConnectorErrorCode.NON_PRIMARY_KEY_CHECK_ERROR, message);
        }
        this.partitionKeys =
                stringToList(readonlyConfig.get(PaimonSinkOptions.PARTITION_KEYS), ",");
        this.tableOptions =
                new HashMap<>(
                        readonlyConfig
                                .getOptional(SinkConnectorCommonOptions.TABLE_OPTIONS)
                                .orElse(Collections.emptyMap()));
        // Keep write-props as the runtime writer config only; do not merge table_options here.
        this.writeProps = new HashMap<>(readonlyConfig.get(PaimonSinkOptions.WRITE_PROPS));
        this.changelogProducer =
                Stream.of(CoreOptions.ChangelogProducer.values())
                        .filter(
                                cp ->
                                        cp.toString()
                                                .equalsIgnoreCase(
                                                        writeProps.getOrDefault(

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove the `primary_keys` entry from the sink config when `non_primary_key = true`
  2. Or set `non_primary_key = false` if the table really should be a primary-key table
  3. Check the generated/template config for a hardcoded primary_keys default

Example fix

// before
non_primary_key = true
primary_keys = ["id"]
// after
non_primary_key = true
Defensive patterns

Strategy: validation

Validate before calling

if (config.get(PaimonSinkOptions.NON_PRIMARY_KEY) && !config.get(PaimonSinkOptions.PRIMARY_KEYS).isEmpty()) { throw new IllegalArgumentException("primary_keys must be empty when non_primary_key = true"); }

Try / catch

try { new PaimonSinkConfig(readonlyConfig); } catch (PaimonConnectorException e) { if (PaimonConnectorErrorCode.NON_PRIMARY_KEY_CHECK_ERROR.equals(e.getErrorCode())) { /* strip primary_keys and rebuild */ } else { throw e; } }

Prevention

When it happens

Trigger: Constructing PaimonSinkConfig where readonlyConfig has non_primary_key=true AND a non-empty primary_keys list (e.g. leftover primary_keys from a copied HOCON config).

Common situations: Users switch a table to append/non-pk mode by setting non_primary_key=true but forget to delete the primary_keys line; template configs that predefine primary_keys; automated config generation that always emits primary_keys.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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