apache/seatunnel · error · OptionValidationException

tables_configs[%d]: 'start_mode.offsets' is only valid when

Error message

tables_configs[%d]: 'start_mode.offsets' is only valid when start_mode=SPECIFIC_OFFSETS

What it means

In tables_configs, start_mode.offsets is only meaningful when start_mode=SPECIFIC_OFFSETS. evaluate() rejects entries that set start_mode=TIMESTAMP but also supply start_mode.offsets, since the two start strategies conflict.

Source

Thrown at seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaSourceFactory.java:215

        @Override
        public boolean evaluate(ReadonlyConfig config, List<Map<String, Object>> entries)
                throws OptionValidationException {
            if (entries == null || entries.isEmpty()) {
                return true;
            }
            for (int i = 0; i < entries.size(); i++) {
                ReadonlyConfig entryConfig = ReadonlyConfig.fromMap(entries.get(i));
                StartMode startMode =
                        entryConfig.getOptional(KafkaSourceOptions.START_MODE).orElse(null);
                if (startMode == StartMode.TIMESTAMP) {
                    Long ts = entryConfig.get(KafkaSourceOptions.START_MODE_TIMESTAMP);
                    if (ts == null || ts < 0) {
                        throw new OptionValidationException(
                                "tables_configs[%d]: 'start_mode.timestamp' must be >= 0, got: %d",
                                i, ts);
                    }
                    if (entries.get(i).containsKey(KafkaSourceOptions.START_MODE_OFFSETS.key())) {
                        throw new OptionValidationException(
                                "tables_configs[%d]: 'start_mode.offsets' is only valid "
                                        + "when start_mode=SPECIFIC_OFFSETS",
                                i);
                    }
                    Long endTs = entryConfig.get(KafkaSourceOptions.START_MODE_END_TIMESTAMP);
                    if (endTs != null && endTs < 0) {
                        throw new OptionValidationException(
                                "tables_configs[%d]: 'start_mode.end_timestamp' must be >= 0, got: %d",
                                i, endTs);
                    }
                } else if (startMode == StartMode.SPECIFIC_OFFSETS) {
                    Map<String, Long> offsets =
                            entryConfig.get(KafkaSourceOptions.START_MODE_OFFSETS);
                    if (offsets == null || offsets.isEmpty()) {
                        throw new OptionValidationException(
                                "tables_configs[%d]: 'start_mode.offsets' must not be empty "
                                        + "when start_mode=SPECIFIC_OFFSETS",
                                i);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove start_mode.offsets from entries where start_mode=TIMESTAMP.
  2. Change start_mode to SPECIFIC_OFFSETS if you actually want explicit offsets.
  3. Audit each tables_configs entry for mutually exclusive options before submission.

Example fix

// before
start_mode = TIMESTAMP
start_mode.timestamp = 1704067200000
start_mode.offsets = {partition-0: 100}
// after
start_mode = TIMESTAMP
start_mode.timestamp = 1704067200000
Defensive patterns

Strategy: validation

Validate before calling

if (!"SPECIFIC_OFFSETS".equals(entry.get("start_mode")) && entry.containsKey("start_mode.offsets")) { throw new IllegalArgumentException("start_mode.offsets requires start_mode=SPECIFIC_OFFSETS"); }

Try / catch

try { factory.evaluate(ctx); } catch (OptionValidationException e) { stripConflictingOptions(ctx); reevaluate(ctx); }

Prevention

When it happens

Trigger: A tables_configs entry combining start_mode=TIMESTAMP with a start_mode.offsets map present (even empty); detected in KafkaSourceFactory.evaluate at job build time.

Common situations: Merging/reusing per-table config blocks that accumulate stale options; template configs carrying offsets plus a later-switched timestamp mode.

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