apache/seatunnel · error · PulsarConnectorException
SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED
SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED
Error message
tables_configs cannot be empty
What it means
PulsarMultiTableConfig.parseMultiTable validates the 'tables_configs' list; an empty list provides no tables to read, so it throws PulsarConnectorException with SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED. At least one table entry is required for multi-table Pulsar sources.
Source
Thrown at seatunnel-connectors-v2/connector-pulsar/src/main/java/org/apache/seatunnel/connectors/seatunnel/pulsar/config/PulsarMultiTableConfig.java:132
topic,
topicPattern != null ? Pattern.compile(topicPattern) : null,
format,
startMode,
startTimestamp,
stopMode,
stopTimestamp,
resetMode,
subscriptionName,
config);
return new PulsarMultiTableConfig(
java.util.Collections.singletonList(tableConfig), config, false, false);
}
private static PulsarMultiTableConfig parseMultiTable(ReadonlyConfig config) {
List<Map<String, Object>> tablesConfigs = config.get(TableSchemaOptions.TABLE_CONFIGS);
if (tablesConfigs.isEmpty()) {
throw new PulsarConnectorException(
SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED,
"tables_configs cannot be empty");
}
List<PulsarTableConfig> tableConfigs = new ArrayList<>();
Map<String, Integer> tablePathIndexes = new LinkedHashMap<>();
Map<String, Integer> explicitTopicIndexes = new LinkedHashMap<>();
Map<String, Integer> topicPatternIndexes = new LinkedHashMap<>();
List<PatternEntry> knownPatterns = new ArrayList<>();
for (int i = 0; i < tablesConfigs.size(); i++) {
Map<String, Object> tableConfigMap = tablesConfigs.get(i);
ReadonlyConfig tableConfig = mergeWithGlobal(config, tableConfigMap);
String topic = tableConfig.getOptional(PulsarSourceOptions.TOPIC).orElse(null);
String topicPatternStr =
tableConfig.getOptional(PulsarSourceOptions.TOPIC_PATTERN).orElse(null);
if ((topic == null && topicPatternStr == null)View on GitHub (pinned to cf67b549a7)
Solutions
- Populate tables_configs with at least one entry containing topic/topic-pattern, subscription.name, and schema.
- If you intend a single-table read, use the single-table config style (topic at top level) instead of empty tables_configs.
- Check templating/variable substitution isn't producing an empty list at runtime.
Example fix
// before
tables_configs = []
// after
tables_configs = [
{
topic = "persistent://public/default/orders"
"subscription.name" = "seatunnel-sub"
}
] Defensive patterns
Strategy: validation
Validate before calling
List<Map<String,Object>> tables = config.get(TableSchemaOptions.TABLE_CONFIGS);
if (tables == null || tables.isEmpty()) throw new IllegalArgumentException("tables_configs must contain at least one entry"); Prevention
- Validate HOCON config locally before job submission
- Check templating/variable output isn't producing an empty list
- Prefer single-table syntax when only one topic is needed
- Keep a checked-in example config with a populated tables_configs
When it happens
Trigger: PulsarSource config parsed via PulsarMultiTableConfig.of where tables_configs key is present but resolves to an empty list ([]).
Common situations: User defines tables_configs = [] (or the list is produced empty by templating/env substitution) instead of configuring table entries; copy-pasting a skeleton config without filling it in.
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
- CommonErrorCode.ILLEGAL_ARGUMENT
- SeaTunnelAPIErrorCode.OPTION_VALIDATION_FAILED
- SeaTunnelAPIErrorCode.CONFIG_VALIDATION_FAILED
- PulsarConnectorErrorCode.DESERIALIZATION_SCHEMA_NOT_FOUND
- MultiTableWriterRunnable can't find writer for tableId:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/786c3cc9879266a1.
Report an issue: GitHub.