{"record":{"id":"ee1aa48df7016568","repo":"apache/seatunnel","slug":"startup-specific-offset-options-can-only-be-us","errorCode":null,"errorMessage":"'startup.specific-offset.*' options can only be used when '${SourceOptions.STARTUP_MODE_KEY}' is 'specific', but current mode is '${startupMode}'.","messagePattern":"'startup\\.specific-offset\\.\\*' options can only be used when '(.+?)' is 'specific', but current mode is '(.+?)'\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/MySqlIncrementalSource.java","lineNumber":193,"sourceCode":"                            gtidSet),\n                    e);\n        }\n        return Optional.of(gtidSet);\n    }\n\n    private static long getNonNegativeSkipValue(ReadonlyConfig config, Option<Long> option) {\n        long value = config.getOptional(option).orElse(0L);\n        if (value < 0) {\n            throw new IllegalArgumentException(\n                    String.format(\"'%s' must be greater than or equal to 0.\", option.key()));\n        }\n        return value;\n    }\n\n    private static void validateNoSpecificStartupOffset(\n            ReadonlyConfig config, StartupMode startupMode) {\n        if (hasSpecificStartupOffset(config)) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"'startup.specific-offset.*' options can only be used when '%s' is 'specific', but current mode is '%s'.\",\n                            SourceOptions.STARTUP_MODE_KEY, startupMode));\n        }\n    }\n\n    private static boolean hasSpecificStartupOffset(ReadonlyConfig config) {\n        return config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE).isPresent()\n                || config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_POS).isPresent()\n                || config.getOptional(\n                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_GTID_SET)\n                        .isPresent()\n                || config.getOptional(\n                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_EVENTS)\n                        .isPresent()\n                || config.getOptional(\n                                MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_ROWS)\n                        .isPresent();","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/MySqlIncrementalSource.java#L175-L211","documentation":"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.).","triggerScenarios":"createStartupConfig calling validateNoSpecificStartupOffset when hasSpecificStartupOffset(config) is true but startupMode != SPECIFIC (e.g. startup.mode='latest' with a leftover specific-offset.file).","commonSituations":"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.","solutions":["Remove all startup.specific-offset.* keys, or set startup.mode='specific' to actually use them","Audit the config for leftover specific-offset entries after changing startup.mode","If resuming from a known offset is the goal, keep mode='specific' and supply file+pos"],"exampleFix":"// before\nstartup {\n  mode = \"latest\"\n  specific-offset.file = \"mysql-bin.000003\"\n  specific-offset.pos = 4\n}\n// after\nstartup { mode = \"latest\" }","handlingStrategy":"validation","validationCode":"String mode = config.getString(\"startup.mode\");\nif (!mode.equals(\"specific\") && (config.hasPath(\"startup.specific-offset.file\") || config.hasPath(\"startup.specific-offset.pos\") || config.hasPath(\"startup.specific-offset.gtid-set\"))) {\n    throw new IllegalArgumentException(\"specific-offset.* keys require startup.mode='specific'\");\n}","typeGuard":null,"tryCatchPattern":"try { createSource(config); } catch (IllegalArgumentException e) { LOG.error(\"Mode/offset mismatch: {}\", e.getMessage()); throw new ConfigException(e); }","preventionTips":["When changing startup.mode, delete the whole startup block and rebuild it","Keep mode-specific config sections in separate profiles","Grep configs in CI for specific-offset keys not under mode='specific'"],"tags":["cdc","mysql","config-validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}