apache/seatunnel · error · OptionValidationException
tables_configs[ ]: 'topics' must not be empty
Error message
tables_configs[%d]: 'topics' must not be empty
What it means
RocketMqSourceFactory.validate validates each entry of `tables_configs` at option-rule evaluation time. Each table entry must define a non-empty `topics` option; otherwise OptionValidationException is thrown with the entry index. This fails fast before any job resources are allocated.
Solutions
- Add a non-empty `topics` value (comma-separated topic list) to every entry in tables_configs
- Check YAML indentation so `topics` actually lands inside the intended table entry
- Verify no entry has only whitespace, e.g. topics: " " which also fails validation
Example fix
// before
tables_configs = [
{ topic = "" }
]
// after
tables_configs = [
{ topics = "order-events" }
] Defensive patterns
Strategy: validation
Validate before calling
config.getTablesConfigs().forEach(tc -> {
String topics = tc.get("topics");
if (topics == null || topics.trim().isEmpty())
throw new IllegalArgumentException("every tables_configs entry needs non-empty 'topics'");
}); Prevention
- Keep a reviewed config template for multi-table sources
- Run the connector's option validation (factory evaluate) locally before production submits
- Avoid whitespace placeholder values like topics: " "
When it happens
Trigger: A `tables_configs` entry where `topics` is absent, null, empty string, or whitespace-only, detected in evaluate() while parsing entry i.
Common situations: Multi-table configs where one entry was pasted incompletely, YAML indentation errors leaving `topics` unset for one table, or `topics: ""` left as a placeholder.
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
- tables_configs[ ]: 'start.mode.offsets' must not be empty…
- tables_configs[ ]: 'start.mode.timestamp' must be >= 0, got
- tables_configs[ ]: 'start.mode.timestamp' required when…
- At least one sink plugin must be configured.
- At least one source plugin must be configured.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/29d9c065571ee751.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/source/RocketMqSourceFactory.java:132
@Override
public String description() {
return "each tables_configs entry must have valid topics, "
+ "start.mode.timestamp (>= 0) when CONSUME_FROM_TIMESTAMP, "
+ "and non-empty start.mode.offsets when CONSUME_FROM_SPECIFIC_OFFSETS";
}
@Override
public boolean evaluate(ReadonlyConfig config, List<Map<String, Object>> entries)
throws OptionValidationException {
if (entries == null || entries.isEmpty()) {
return true;
}
for (int i = 0; i < entries.size(); i++) {
ReadonlyConfig tableConfig = ReadonlyConfig.fromMap(entries.get(i));
String topics = tableConfig.get(RocketMqSourceOptions.TOPICS);
if (topics == null || topics.trim().isEmpty()) {
throw new OptionValidationException(
"tables_configs[%d]: 'topics' must not be empty", i);
}
StartMode startMode =
tableConfig.getOptional(RocketMqSourceOptions.START_MODE).orElse(null);
if (startMode == StartMode.CONSUME_FROM_TIMESTAMP) {
Long ts =
tableConfig
.getOptional(RocketMqSourceOptions.START_MODE_TIMESTAMP)
.orElse(null);
if (ts == null) {
throw new OptionValidationException(
"tables_configs[%d]: 'start.mode.timestamp' required "
+ "when start.mode=CONSUME_FROM_TIMESTAMP",
i);
}
if (ts < 0) {
throw new OptionValidationException(
"tables_configs[%d]: 'start.mode.timestamp' must be >= 0, got: %d",View on GitHub (pinned to cf67b549a7)