{"record":{"id":"2d7641671dcd56b4","repo":"apache/seatunnel","slug":"tables-configs-d-start-mode-offsets-must-not","errorCode":null,"errorMessage":"tables_configs[%d]: 'start_mode.offsets' must not be empty when start_mode=SPECIFIC_OFFSETS","messagePattern":"tables_configs\\[(.+?)\\]: 'start_mode\\.offsets' must not be empty when start_mode=SPECIFIC_OFFSETS","errorType":"validation","errorClass":"OptionValidationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaSourceFactory.java","lineNumber":230,"sourceCode":"                                i, ts);\n                    }\n                    if (entries.get(i).containsKey(KafkaSourceOptions.START_MODE_OFFSETS.key())) {\n                        throw new OptionValidationException(\n                                \"tables_configs[%d]: 'start_mode.offsets' is only valid \"\n                                        + \"when start_mode=SPECIFIC_OFFSETS\",\n                                i);\n                    }\n                    Long endTs = entryConfig.get(KafkaSourceOptions.START_MODE_END_TIMESTAMP);\n                    if (endTs != null && endTs < 0) {\n                        throw new OptionValidationException(\n                                \"tables_configs[%d]: 'start_mode.end_timestamp' must be >= 0, got: %d\",\n                                i, endTs);\n                    }\n                } else if (startMode == StartMode.SPECIFIC_OFFSETS) {\n                    Map<String, Long> offsets =\n                            entryConfig.get(KafkaSourceOptions.START_MODE_OFFSETS);\n                    if (offsets == null || offsets.isEmpty()) {\n                        throw new OptionValidationException(\n                                \"tables_configs[%d]: 'start_mode.offsets' must not be empty \"\n                                        + \"when start_mode=SPECIFIC_OFFSETS\",\n                                i);\n                    }\n                    if (entries.get(i).containsKey(KafkaSourceOptions.START_MODE_TIMESTAMP.key())) {\n                        throw new OptionValidationException(\n                                \"tables_configs[%d]: 'start_mode.timestamp' is only valid \"\n                                        + \"when start_mode=TIMESTAMP\",\n                                i);\n                    }\n                } else if (entries.get(i).containsKey(KafkaSourceOptions.START_MODE_TIMESTAMP.key())\n                        || entries.get(i)\n                                .containsKey(KafkaSourceOptions.START_MODE_OFFSETS.key())) {\n                    throw new OptionValidationException(\n                            \"tables_configs[%d]: 'start_mode.timestamp' and \"\n                                    + \"'start_mode.offsets' require an appropriate start_mode\",\n                            i);\n                }","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaSourceFactory.java#L212-L248","documentation":"When a tables_configs entry uses start_mode=SPECIFIC_OFFSETS, evaluate() requires a non-empty start_mode.offsets map. A null or empty map cannot define any partition offset, so OptionValidationException is thrown.","triggerScenarios":"start_mode=SPECIFIC_OFFSETS with start_mode.offsets absent, null, or {} in a tables_configs entry; checked in KafkaSourceFactory.evaluate.","commonSituations":"Generated configs where offsets substitution failed to populate; empty maps from templating; forgetting offsets after switching from TIMESTAMP mode.","solutions":["Provide start_mode.offsets as a non-empty map of partition offsets, e.g. {\"partition-0\": 100}.","Choose a different start_mode (earliest/latest/timestamp) if explicit offsets aren't available.","Check the entry index in the message to locate the offending table config."],"exampleFix":"// before\nstart_mode = SPECIFIC_OFFSETS\nstart_mode.offsets = {}\n// after\nstart_mode = SPECIFIC_OFFSETS\nstart_mode.offsets = {\"partition-0\": 100, \"partition-1\": 42}","handlingStrategy":"validation","validationCode":"Map<String,Long> offsets = entry.get(\"start_mode.offsets\");\nif (\"SPECIFIC_OFFSETS\".equals(entry.get(\"start_mode\")) && (offsets == null || offsets.isEmpty())) throw new IllegalArgumentException(\"start_mode.offsets must be non-empty\");","typeGuard":null,"tryCatchPattern":"try { factory.evaluate(ctx); } catch (OptionValidationException e) { log.error(\"Supply offsets per: {}\", e.getMessage()); }","preventionTips":["Verify offset map population when generating configs from templates.","Fail fast on empty offsets in config preprocessing."],"tags":["kafka","config","validation","offsets"],"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"}