apache/seatunnel · error · IllegalArgumentException

'startup.specific-offset.*' options can only be used when '$

Error message

'startup.specific-offset.*' options can only be used when '${SourceOptions.STARTUP_MODE_KEY}' is 'specific', but current mode is '${startupMode}'.

What it means

The startup.specific-offset.* keys (file, pos, gtid-set, skip-*) are only meaningful when startup.mode='specific'. validateNoSpecificStartupOffset throws IllegalArgumentException if any of them is set while the effective startup mode is something else (initial, latest, etc.).

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/MySqlIncrementalSource.java:193

                            gtidSet),
                    e);
        }
        return Optional.of(gtidSet);
    }

    private static long getNonNegativeSkipValue(ReadonlyConfig config, Option<Long> option) {
        long value = config.getOptional(option).orElse(0L);
        if (value < 0) {
            throw new IllegalArgumentException(
                    String.format("'%s' must be greater than or equal to 0.", option.key()));
        }
        return value;
    }

    private static void validateNoSpecificStartupOffset(
            ReadonlyConfig config, StartupMode startupMode) {
        if (hasSpecificStartupOffset(config)) {
            throw new IllegalArgumentException(
                    String.format(
                            "'startup.specific-offset.*' options can only be used when '%s' is 'specific', but current mode is '%s'.",
                            SourceOptions.STARTUP_MODE_KEY, startupMode));
        }
    }

    private static boolean hasSpecificStartupOffset(ReadonlyConfig config) {
        return config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE).isPresent()
                || config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_POS).isPresent()
                || config.getOptional(
                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET)
                        .isPresent()
                || config.getOptional(
                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_EVENTS)
                        .isPresent()
                || config.getOptional(
                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_ROWS)
                        .isPresent();

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove all startup.specific-offset.* keys, or set startup.mode='specific' to actually use them
  2. Audit the config for leftover specific-offset entries after changing startup.mode
  3. If resuming from a known offset is the goal, keep mode='specific' and supply file+pos

Example fix

// before
startup {
  mode = "latest"
  specific-offset.file = "mysql-bin.000003"
  specific-offset.pos = 4
}
// after
startup { mode = "latest" }
Defensive patterns

Strategy: validation

Validate before calling

String mode = config.getString("startup.mode");
if (!mode.equals("specific") && (config.hasPath("startup.specific-offset.file") || config.hasPath("startup.specific-offset.pos") || config.hasPath("startup.specific-offset.gtid-set"))) {
    throw new IllegalArgumentException("specific-offset.* keys require startup.mode='specific'");
}

Try / catch

try { createSource(config); } catch (IllegalArgumentException e) { LOG.error("Mode/offset mismatch: {}", e.getMessage()); throw new ConfigException(e); }

Prevention

When it happens

Trigger: createStartupConfig calling validateNoSpecificStartupOffset when hasSpecificStartupOffset(config) is true but startupMode != SPECIFIC (e.g. startup.mode='latest' with a leftover specific-offset.file).

Common situations: Switching startup.mode from 'specific' back to 'latest'/'initial' without deleting the old offset keys; copy-pasted config that kept stale specific-offset entries; user expects the offset to be honored in other modes.

Related errors


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