{"record":{"id":"bddd7ae59b802150","repo":"apache/seatunnel","slug":"tables-configs-d-keys-must-be-configured-and","errorCode":null,"errorMessage":"tables_configs[%d]: 'keys' must be configured and non-blank","messagePattern":"tables_configs\\[(.+?)\\]: 'keys' must be configured and non-blank","errorType":"validation","errorClass":"OptionValidationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-redis/src/main/java/org/apache/seatunnel/connectors/seatunnel/redis/config/RedisTableConfigsValidator.java","lineNumber":41,"sourceCode":"\nimport java.util.List;\nimport java.util.Map;\n\npublic class RedisTableConfigsValidator implements ConditionExtension<List<Map<String, Object>>> {\n\n    @Override\n    public String description() {\n        return \"each 'tables_configs' entry must declare a non-blank 'keys' and a 'data_type'\";\n    }\n\n    @Override\n    public boolean evaluate(ReadonlyConfig config, List<Map<String, Object>> entries)\n            throws OptionValidationException {\n        for (int i = 0; i < entries.size(); i++) {\n            ReadonlyConfig entry = ReadonlyConfig.fromMap(entries.get(i));\n            String keys = entry.getOptional(RedisBaseOptions.KEY_PATTERN).orElse(null);\n            if (keys == null || keys.trim().isEmpty()) {\n                throw new OptionValidationException(\n                        \"tables_configs[%d]: 'keys' must be configured and non-blank\", i);\n            }\n            if (!entry.getOptional(RedisBaseOptions.DATA_TYPE).isPresent()) {\n                throw new OptionValidationException(\n                        \"tables_configs[%d]: 'data_type' must be configured\", i);\n            }\n        }\n        return true;\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":52,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-redis/src/main/java/org/apache/seatunnel/connectors/seatunnel/redis/config/RedisTableConfigsValidator.java#L23-L52","documentation":"Validation of the `tables_configs` option failed for at least one entry because its 'keys' field is absent, null, or blank. RedisTableConfigsValidator.evaluate() reads RedisBaseOptions.KEY_PATTERN from each entry and requires a non-empty, non-whitespace key pattern; without it the connector cannot know which Redis keys the table covers.","triggerScenarios":"evaluate() processes tables_configs entries as ReadonlyConfig maps; entry i has no `keys` value, or `keys = \"\"` / `keys = \"   \"` (whitespace-only), triggering the OptionValidationException at this line.","commonSituations":"Omitting `keys` when defining per-table configs, leaving the value empty after removing a pattern, or YAML/env templating that collapses an unset variable to an empty string.","solutions":["Add a non-blank `keys` value (a key pattern like \"user:*\") to every tables_configs entry.","If the value is templated, ensure the placeholder resolves to a real pattern.","Remove genuinely empty entries from tables_configs instead of leaving them with blank keys."],"exampleFix":"// before\ntables_configs = [{ data_type = \"string\" }]\n// after\ntables_configs = [{ keys = \"user:*\", data_type = \"string\" }]","handlingStrategy":"validation","validationCode":"for (Map<String,Object> cfg : tablesConfigs) {\n    Object keys = cfg.get(\"keys\");\n    if (keys == null || keys.toString().trim().isEmpty())\n        throw new IllegalArgumentException(\"tables_configs entry missing keys\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include keys pattern in every tables_configs entry","Check for templating that produces empty strings","Remove truly empty config entries"],"tags":["redis","config-validation","required-field"],"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-23T08:17:48.524Z"}