{"record":{"id":"60b076f48a31a335","repo":"apache/seatunnel","slug":"cannot-specify-both-s-and-root-level-s","errorCode":null,"errorMessage":"Cannot specify both '%s' and root-level '%s'.","messagePattern":"Cannot specify both '(.+?)' and root-level '(.+?)'\\.","errorType":"validation","errorClass":"OptionValidationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-rabbitmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rabbitmq/config/RabbitmqTableConfigsValidator.java","lineNumber":56,"sourceCode":"    private static final String QUEUE_NAME_KEY = RabbitmqBaseOptions.QUEUE_NAME.key();\n    private static final String SCHEMA_KEY = RabbitmqBaseOptions.SCHEMA.key();\n\n    @Override\n    public String description() {\n        return \"requires each entry to declare a non-blank '\"\n                + QUEUE_NAME_KEY\n                + \"' and a '\"\n                + SCHEMA_KEY\n                + \"', and forbids a root-level '\"\n                + SCHEMA_KEY\n                + \"'\";\n    }\n\n    @Override\n    public boolean evaluate(ReadonlyConfig config, List<Map<String, Object>> entries)\n            throws OptionValidationException {\n        if (config.getOptional(RabbitmqBaseOptions.SCHEMA).isPresent()) {\n            throw new OptionValidationException(\n                    \"Cannot specify both '%s' and root-level '%s'.\", TABLE_CONFIGS_KEY, SCHEMA_KEY);\n        }\n        for (int i = 0; i < entries.size(); i++) {\n            ReadonlyConfig entry = ReadonlyConfig.fromMap(entries.get(i));\n            String queueName = entry.getOptional(RabbitmqBaseOptions.QUEUE_NAME).orElse(null);\n            if (queueName == null || queueName.trim().isEmpty()) {\n                throw new OptionValidationException(\n                        \"%s[%d]: '%s' must be configured and non-blank\",\n                        TABLE_CONFIGS_KEY, i, QUEUE_NAME_KEY);\n            }\n\n            if (!entry.getOptional(RabbitmqBaseOptions.SCHEMA).isPresent()) {\n                throw new OptionValidationException(\n                        \"%s[%d]: '%s' must be configured\", TABLE_CONFIGS_KEY, i, SCHEMA_KEY);\n            }\n        }\n\n        return true;","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-rabbitmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rabbitmq/config/RabbitmqTableConfigsValidator.java#L38-L74","documentation":"RabbitmqTableConfigsValidator.evaluate throws OptionValidationException when both tables-configs entries and a root-level schema are present. The two mechanisms are mutually exclusive: either one schema for a single queue, or per-table configs each with their own schema.","triggerScenarios":"User defines tables-configs with entries but also keeps schema at the root of the source config; both keys present in the same HOCON/JSON config.","commonSituations":"Migrating a single-queue config to multi-table mode: user added tables-configs but forgot to delete the old root schema block; merged configs from two examples.","solutions":["Remove the root-level schema option when using tables-configs","Keep schema definitions inside each tables-configs entry instead","Re-run the job after cleaning up so only one schema mechanism is active"],"exampleFix":"// before\nsource {\n  RabbitMQ {\n    schema = { fields { id = int } }\n    tables-configs = [\n      { queue-name = \"q1\", schema = { fields { id = int } } }\n    ]\n  }\n}\n// after\nsource {\n  RabbitMQ {\n    tables-configs = [\n      { queue-name = \"q1\", schema = { fields { id = int } } }\n    ]\n  }\n}","handlingStrategy":"validation","validationCode":"ReadonlyConfig cfg = ReadonlyConfig.fromMap(jobConfig);\nif (cfg.getOptional(RabbitmqBaseOptions.TABLE_CONFIGS).isPresent()\n    && cfg.getOptional(RabbitmqBaseOptions.SCHEMA).isPresent()) {\n  throw new IllegalArgumentException(\"Remove root-level schema when tables-configs is used\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  tablesConfigsValidator.evaluate(config, entries);\n} catch (OptionValidationException e) {\n  System.err.println(\"Conflicting options: \" + e.getMessage());\n}","preventionTips":["Use exactly one schema mechanism: root schema OR tables-configs","When migrating single-queue to multi-table configs, delete the old schema block","Run config validation in CI before deploying jobs"],"tags":["rabbitmq","config","validation","mutually-exclusive"],"backgroundTag":"conflicting-config-options","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}