{"record":{"id":"77d938a857ab9509","repo":"apache/seatunnel","slug":"tables-configs-can-not-be-empty-77d938","errorCode":null,"errorMessage":"tables_configs can not be empty.","messagePattern":"tables_configs can not be empty\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-vitess/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/vitess/source/VitessSourceFactory.java","lineNumber":140,"sourceCode":"    private List<CatalogTable> resolveCatalogTables(TableSourceFactoryContext context) {\n        validateSchemaMetadataContract(context);\n        validateSelectionOptions(context);\n        return filterDeclaredTables(context, discoverTableSchemas(context));\n    }\n\n    private void validateSchemaMetadataContract(TableSourceFactoryContext context) {\n        Optional<Map<String, Object>> singleSchema =\n                context.getOptions().getOptional(ConnectorCommonOptions.SCHEMA);\n        Optional<List<Map<String, Object>>> tableConfigs =\n                context.getOptions().getOptional(ConnectorCommonOptions.TABLE_CONFIGS);\n        if (singleSchema.isPresent()) {\n            validateRootSchemaDefinition(singleSchema.get(), \"schema\");\n            return;\n        }\n        if (tableConfigs.isPresent()) {\n            List<Map<String, Object>> configs = tableConfigs.get();\n            if (configs.isEmpty()) {\n                throw new IllegalArgumentException(\"tables_configs can not be empty.\");\n            }\n            for (int index = 0; index < configs.size(); index++) {\n                validateSchemaDefinition(configs.get(index), \"tables_configs[\" + index + \"]\");\n            }\n            return;\n        }\n        throw new IllegalArgumentException(\n                \"Vitess CDC requires explicit schema metadata through either 'schema' or 'tables_configs'.\");\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private void validateRootSchemaDefinition(Map<String, Object> schema, String optionName) {\n        if (!schema.containsKey(ColumnOptions.COLUMNS.key())\n                && !schema.containsKey(ColumnOptions.METADATA_TABLE_ID.key())) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"Vitess CDC requires explicit columns or metadata_table_id in '%s' so table schemas stay deterministic.\",\n                            optionName));","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-vitess/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/vitess/source/VitessSourceFactory.java#L122-L158","documentation":"Thrown in validateSchemaMetadataContract when the tables_configs option is provided but the list is empty. The factory requires schema metadata for every table; an empty list is treated as a configuration error rather than silently falling back.","triggerScenarios":"Calling VitessSourceFactory.resolveCatalogTables with tables_configs configured as an empty array/map list (configs.isEmpty() is true).","commonSituations":"Template variables that expanded to an empty list; deleting all entries from tables_configs while leaving the key; automated config generation emitting '[]'.","solutions":["Add at least one table config entry with a schema block to tables_configs","Remove the tables_configs key entirely and use the 'schema' option instead","Fix the templating/pipeline that produced the empty list"],"exampleFix":"// before\ntables_configs = []\n// after\ntables_configs = [\n  { table-names = \"commerce.orders\"\n    schema { columns { id = bigint } } }\n]","handlingStrategy":"validation","validationCode":"List<Map<String,Object>> configs = options.get(TABLES_CONFIGS);\nif (configs != null && configs.isEmpty()) {\n    throw new IllegalArgumentException(\"tables_configs must not be empty\");\n}","typeGuard":null,"tryCatchPattern":"try { factory.resolveCatalogTables(context); } catch (IllegalArgumentException e) { /* populate tables_configs or drop the key */ }","preventionTips":["Treat 'empty list' and 'absent' as distinct config states in tooling","Never emit tables_configs = [] from templates","Add a pre-submit config linter"],"tags":["cdc","vitess","empty-list","config-validation"],"backgroundTag":"empty-required-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}