{"record":{"id":"1b442cd86af87417","repo":"apache/seatunnel","slug":"sourceoptions-startup-mode-key-requires-so","errorCode":null,"errorMessage":"'${SourceOptions.STARTUP_MODE_KEY}' requires '${SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE.key()}' with '${SourceOptions.STARTUP_SPECIFIC_OFFSET_POS.key()}' when the mode is 'specific'.","messagePattern":"'(.+?)' requires '(.+?)' with '(.+?)' when the mode is 'specific'\\.","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":117,"sourceCode":"     * GTID and skip fields are optional metadata on that same offset, not an alternative anchor.\n     */\n    private static Map<String, String> createSpecificStartupOffset(ReadonlyConfig config) {\n        Optional<String> gtidSet = getValidatedGtidSet(config);\n        boolean hasFile =\n                config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE).isPresent();\n        boolean hasPos = config.getOptional(SourceOptions.STARTUP_SPECIFIC_OFFSET_POS).isPresent();\n\n        if (hasFile != hasPos) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"'%s' and '%s' must be configured together when '%s' is 'specific'.\",\n                            SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE.key(),\n                            SourceOptions.STARTUP_SPECIFIC_OFFSET_POS.key(),\n                            SourceOptions.STARTUP_MODE_KEY));\n        }\n\n        if (!hasFile) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"'%s' requires '%s' with '%s' when the mode is 'specific'.\",\n                            SourceOptions.STARTUP_MODE_KEY,\n                            SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE.key(),\n                            SourceOptions.STARTUP_SPECIFIC_OFFSET_POS.key()));\n        }\n\n        long skipEvents =\n                getNonNegativeSkipValue(\n                        config, MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_EVENTS);\n        long skipRows =\n                getNonNegativeSkipValue(\n                        config, MySqlIncrementalSourceOptions.STARTUP_SPECIFIC_OFFSET_SKIP_ROWS);\n\n        Map<String, String> offset = new LinkedHashMap<>();\n        String file = config.get(SourceOptions.STARTUP_SPECIFIC_OFFSET_FILE);\n        if (StringUtils.isBlank(file)) {\n            throw new IllegalArgumentException(","sourceCodeStart":99,"sourceCodeEnd":135,"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#L99-L135","documentation":"When startup.mode=specific, an explicit binlog offset is mandatory. If neither specific-offset.file nor specific-offset.pos is configured, MySqlIncrementalSource cannot construct the required offset and throws this IllegalArgumentException.","triggerScenarios":"createSpecificStartupOffset (via createStartupConfig) invoked with startup.mode='specific' but startup.specific-offset.file absent entirely (hasFile=false).","commonSituations":"User sets startup.mode='specific' but forgets to add the offset keys; mode renamed/changed from a different startup mode without removing/adding the matching options; copied config where offset block was commented out.","solutions":["Add startup.specific-offset.file and startup.specific-offset.pos to the config when using startup.mode='specific'","Switch startup.mode to 'initial' (snapshot) or 'latest' (tail binlog) if a specific offset isn't required","Get a valid filename/position from SHOW BINARY LOG STATUS (or SHOW MASTER STATUS on older MySQL) on the source server"],"exampleFix":"// before\nstartup { mode = \"specific\" }\n// after\nstartup {\n  mode = \"specific\"\n  specific-offset.file = \"mysql-bin.000003\"\n  specific-offset.pos = 4\n}","handlingStrategy":"validation","validationCode":"if (config.getString(\"startup.mode\").equals(\"specific\") && !config.hasPath(\"startup.specific-offset.file\")) {\n    throw new IllegalArgumentException(\"mode 'specific' requires startup.specific-offset.file and .pos\");\n}","typeGuard":null,"tryCatchPattern":"try { createSource(config); } catch (IllegalArgumentException e) { LOG.error(\"startup.mode=specific needs specific-offset.file+pos: {}\", e.getMessage()); System.exit(2); }","preventionTips":["Get current coordinates with SHOW BINARY LOG STATUS before using mode='specific'","Keep a documented example config for specific startup mode","Fail fast in CI by submitting a dry-run parse of the job config"],"tags":["cdc","mysql","config-validation"],"backgroundTag":"missing-required-config-field","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"}