apache/seatunnel · error · OptionValidationException
tables_configs[ ]: 'start.mode.timestamp' required when…
Error message
tables_configs[%d]: 'start.mode.timestamp' required when start.mode=CONSUME_FROM_TIMESTAMP
What it means
When a tables_configs entry sets start.mode = CONSUME_FROM_TIMESTAMP, the connector requires `start.mode.timestamp` to be present. evaluate() throws OptionValidationException if the timestamp option is missing. Without it the connector cannot compute the consume-from point.
Solutions
- Add `start.mode.timestamp` (epoch milliseconds) to the table entry that uses CONSUME_FROM_TIMESTAMP
- Or change start.mode to a mode that needs no timestamp (e.g. CONSUME_FROM_LATEST, EARLIEST)
- Confirm the option key spelling matches RocketMqSourceOptions.START_MODE_TIMESTAMP (start.mode.timestamp)
Example fix
// before start.mode = "CONSUME_FROM_TIMESTAMP" // after start.mode = "CONSUME_FROM_TIMESTAMP" start.mode.timestamp = 1700000000000
Defensive patterns
Strategy: validation
Validate before calling
if ("CONSUME_FROM_TIMESTAMP".equals(cfg.get("start.mode")) && cfg.get("start.mode.timestamp") == null)
throw new IllegalArgumentException("start.mode.timestamp required for CONSUME_FROM_TIMESTAMP"); Prevention
- Always set timestamp together with the start mode in your config generator
- Use a lint script that cross-checks start.mode against its companion options
- Document the required pair in your team's config snippets
When it happens
Trigger: Setting `start.mode = "CONSUME_FROM_TIMESTAMP"` in a table entry while omitting `start.mode.timestamp`; detected in RocketMqSourceFactory.evaluate during config validation.
Common situations: Copying a config that used a different start mode, renaming the timestamp key incorrectly, or assuming the timestamp defaults to 'now' — it does not.
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
- tables_configs[ ]: 'start.mode.offsets' must not be empty…
- tables_configs[ ]: 'start.mode.timestamp' must be >= 0, got
- tables_configs[ ]: 'topics' must not be empty
- 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/0ff0ece2fce1ed17.
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:143
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",
i, ts);
}
} else if (startMode == StartMode.CONSUME_FROM_SPECIFIC_OFFSETS) {
Map<String, Long> offsets =
tableConfig
.getOptional(RocketMqSourceOptions.START_MODE_OFFSETS)
.orElse(null);
if (offsets == null || offsets.isEmpty()) {
throw new OptionValidationException(
"tables_configs[%d]: 'start.mode.offsets' must not be empty "
+ "when start.mode=CONSUME_FROM_SPECIFIC_OFFSETS",View on GitHub (pinned to cf67b549a7)