apache/seatunnel · error · OptionValidationException

JDBC XA sink requires max_retries equal to 0 when…

Error message

JDBC XA sink requires max_retries equal to 0 when is_exactly_once=true, otherwise it could cause duplicates.

What it means

JdbcSinkFactory validates option combinations at config-evaluation time. When is_exactly_once=true, the XA transactional sink requires MAX_RETRIES to be 0 because retrying a statement inside an XA transaction can replay already-committed batches, causing duplicate rows. The library throws OptionValidationException during option validation to fail fast at job-creation time.

Solutions

  1. Set max_retries = 0 in the sink configuration when is_exactly_once = true.
  2. If retry behavior is needed, disable is_exactly_once and accept at-least-once semantics with idempotent targets (e.g. primary-key upsert).
  3. Review the sink config block and remove conflicting max_retries overrides from the HOCON/SQL config.

Example fix

// before
sink {
  Jdbc {
    is_exactly_once = "true"
    max_retries = 3
  }
}
// after
sink {
  Jdbc {
    is_exactly_once = "true"
    max_retries = 0
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if (config.getBoolean("is_exactly_once") && config.getInt("max_retries") != 0) {
  throw new IllegalArgumentException("max_retries must be 0 when is_exactly_once=true");
}

Prevention

When it happens

Trigger: Configuring a JDBC sink with is_exactly_once = true while max_retries is set to any value other than 0; the validator (JdbcSinkFactory option validator evaluate()) is invoked when ReadonlyConfig is validated against the Option definitions.

Common situations: Users enable exactly-once semantics for XA-capable databases (MySQL, PostgreSQL, Oracle, DB2) but keep a max_retries value copied from an at-least-once configuration; upgrading from non-XA to XA sink mode without revisiting retry settings.

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/2832aeb1479c962c. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcSinkFactory.java:457

    /**
     * Submission-time validator for {@code is_exactly_once=true}.
     *
     * <p>JDBC XA sink does not support retries; {@code max_retries} must be 0 when exactly-once is
     * enabled, otherwise duplicates may occur.
     */
    static class ExactlyOnceMaxRetriesValidator implements ConditionExtension<Boolean> {
        @Override
        public String description() {
            return "is_exactly_once=true requires max_retries=0";
        }

        @Override
        public boolean evaluate(ReadonlyConfig config, Boolean value)
                throws OptionValidationException {
            if (Boolean.TRUE.equals(value)) {
                int maxRetries = config.get(JdbcSinkOptions.MAX_RETRIES);
                if (maxRetries != 0) {
                    throw new OptionValidationException(
                            "JDBC XA sink requires max_retries equal to 0 when is_exactly_once=true, "
                                    + "otherwise it could cause duplicates.");
                }
            }
            return true;
        }
    }
}

View on GitHub (pinned to cf67b549a7)