apache/seatunnel · error · IllegalArgumentException

'${MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTI

Error message

'${MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET.key()}' must not be blank.

What it means

startup.specific-offset.gtid-set is optional, but if it is configured it must be a non-blank GTID set string. getValidatedGtidSet trims the value and throws IllegalArgumentException when it is empty/whitespace.

Source

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

        if (gtidSet.isPresent()) {
            offset.put(BinlogOffset.GTID_SET_KEY, gtidSet.get());
        }
        offset.put(BinlogOffset.EVENTS_TO_SKIP_OFFSET_KEY, String.valueOf(skipEvents));
        offset.put(BinlogOffset.ROWS_TO_SKIP_OFFSET_KEY, String.valueOf(skipRows));
        return offset;
    }

    /* Validate the configured GTID set before adding it to Debezium's offset map. */
    private static Optional<String> getValidatedGtidSet(ReadonlyConfig config) {
        Optional<String> configuredGtidSet =
                config.getOptional(MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET);
        if (!configuredGtidSet.isPresent()) {
            return Optional.empty();
        }

        String gtidSet = configuredGtidSet.get().trim();
        if (StringUtils.isBlank(gtidSet)) {
            throw new IllegalArgumentException(
                    String.format(
                            "'%s' must not be blank.",
                            MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET.key()));
        }

        try {
            new GtidSet(gtidSet);
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    String.format(
                            "Invalid '%s' value '%s'.",
                            MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET.key(),
                            gtidSet),
                    e);
        }
        return Optional.of(gtidSet);
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Provide a valid GTID set, e.g. "3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5"
  2. Remove the startup.specific-offset.gtid-set key entirely if you don't want GTID-based startup
  3. Obtain the executed GTID set from SELECT @@GLOBAL.gtid_executed on the source

Example fix

// before
specific-offset.gtid-set = ""
// after
specific-offset.gtid-set = "3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5"
Defensive patterns

Strategy: validation

Validate before calling

String gtid = config.getString("startup.specific-offset.gtid-set");
if (gtid != null && gtid.trim().isEmpty()) {
    throw new IllegalArgumentException("gtid-set configured but blank; remove it or supply a valid GTID set");
}

Type guard

boolean nonBlank(String s) { return s != null && !s.trim().isEmpty(); }

Try / catch

try { createSource(config); } catch (IllegalArgumentException e) { LOG.error("Bad gtid-set: {}", e.getMessage()); throw new ConfigException(e); }

Prevention

When it happens

Trigger: getValidatedGtidSet (via createStartupConfig/gtidSet) with a configured specific-offset.gtid-set that is "" or whitespace after trim.

Common situations: Unfilled placeholder gtid-set = ""; env var expansion empty; user intended to disable GTID by blanking the value instead of removing the key.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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