apache/seatunnel · error · IllegalArgumentException

startup.specific-offset.scn is required when startup.mode…

Error message

startup.specific-offset.scn is required when startup.mode is specific.

What it means

With startup.mode = specific, an SCN is mandatory: the connector has no other way to position the redo-log reader. getOracleStartupConfig throws when startup.specific-offset.scn is absent, and also validates the value is > 0, since a non-positive SCN is never a valid resume point.

Solutions

  1. Add startup.specific-offset.scn = <positive SCN> to the config.
  2. Get a valid SCN via SELECT current_scn FROM v$database (or DBMS_FLASHBACK.get_system_change_number).
  3. If a specific start position isn't required, switch startup.mode to initial/latest instead.
  4. Check that any placeholder/variable feeding the SCN actually resolves to a positive number.

Example fix

// before
startup.mode = "specific"
// after
startup.mode = "specific"
startup.specific-offset.scn = 2518210
Defensive patterns

Strategy: validation

Validate before calling

if ("specific".equals(config.get("startup.mode"))) {
    Long scn = config.getOptional("startup.specific-offset.scn").orElse(null);
    if (scn == null || scn <= 0) throw new IllegalArgumentException("startup.specific-offset.scn must be a positive number");
}

Prevention

When it happens

Trigger: startup.mode = "specific" without startup.specific-offset.scn, or with startup.specific-offset.scn <= 0 (e.g. 0 or a negative placeholder).

Common situations: Users set startup.mode = specific but forget the SCN, leave a 0 placeholder, or a templating variable fails to substitute so the key resolves empty/zero.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/oracle/source/OracleIncrementalSource.java:135

        }

        if (config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE).isPresent()
                || config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_POS).isPresent()) {
            throw new IllegalArgumentException(
                    "Oracle-CDC specific startup mode uses "
                            + OracleIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SCN.key()
                            + " instead of file or position offsets.");
        }

        Long scn =
                startupSpecificOffsetScn.orElseThrow(
                        () ->
                                new IllegalArgumentException(
                                        OracleIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SCN
                                                        .key()
                                                + " is required when startup.mode is specific."));
        if (scn <= 0) {
            throw new IllegalArgumentException(
                    OracleIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SCN.key()
                            + " must be greater than 0.");
        }

        Map<String, String> specificOffset = new HashMap<>();
        specificOffset.put(RedoLogOffset.SCN_KEY, String.valueOf(scn));
        specificOffset.put(RedoLogOffset.COMMIT_SCN_KEY, "0");
        specificOffset.put(RedoLogOffset.LCR_POSITION_KEY, null);
        return new StartupConfig(StartupMode.SPECIFIC, specificOffset);
    }

    @Override
    public SourceConfig.Factory<JdbcSourceConfig> createSourceConfigFactory(ReadonlyConfig config) {
        OracleSourceConfigFactory configFactory = new OracleSourceConfigFactory();
        configFactory.fromReadonlyConfig(readonlyConfig);
        configFactory.startupOptions(startupConfig);
        configFactory.stopOptions(stopConfig);
        configFactory.schemaList(config.get(OracleIncrementalSourceOptions.SCHEMA_NAMES));

View on GitHub (pinned to cf67b549a7)