{"record":{"id":"f3c6f0ca6776bdbd","repo":"apache/seatunnel","slug":"vitess-cdc-requires-database-qualified-table-paths","errorCode":null,"errorMessage":"Vitess CDC requires database-qualified table paths, but table '%s' does not define a database name.","messagePattern":"Vitess CDC requires database-qualified table paths, but table '(.+?)' does not define a database name\\.","errorType":"exception","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/config/VitessSourceConfig.java","lineNumber":92,"sourceCode":"    }\n\n    /**\n     * Builds the validated connector configuration.\n     *\n     * <p>Vitess does not expose database/schema names the same way as MySQL-based connectors, so\n     * table paths must already be deterministic before the source starts.\n     */\n    public static VitessSourceConfig of(ReadonlyConfig options, List<CatalogTable> catalogTables) {\n        if (catalogTables == null || catalogTables.isEmpty()) {\n            throw new IllegalArgumentException(\n                    \"Vitess CDC requires resolved catalog tables for deterministic table identity.\");\n        }\n\n        String keyspace = options.get(VitessSourceOptions.KEYSPACE);\n        for (CatalogTable catalogTable : catalogTables) {\n            String databaseName = catalogTable.getTablePath().getDatabaseName();\n            if (databaseName == null) {\n                throw new IllegalArgumentException(\n                        String.format(\n                                \"Vitess CDC requires database-qualified table paths, but table '%s' does not define a database name.\",\n                                catalogTable.getTablePath()));\n            }\n            if (!keyspace.equals(databaseName)) {\n                throw new IllegalArgumentException(\n                        String.format(\n                                \"Vitess CDC captures one keyspace per source. Table '%s' does not belong to keyspace '%s'.\",\n                                catalogTable.getTablePath(), keyspace));\n            }\n            if (catalogTable.getTablePath().getSchemaName() != null) {\n                throw new IllegalArgumentException(\n                        String.format(\n                                \"Vitess CDC does not support schema-qualified table paths. Table '%s' contains an unexpected schema component.\",\n                                catalogTable.getTablePath()));\n            }\n        }\n","sourceCodeStart":74,"sourceCodeEnd":110,"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/config/VitessSourceConfig.java#L74-L110","documentation":"VitessSourceConfig.of validates that every resolved CatalogTable has a database-qualified TablePath (a non-null database name), because Vitess table identity is keyspace-scoped and the connector must map each table to its keyspace. A table path without a database name cannot be attributed to a keyspace and fails fast.","triggerScenarios":"A CatalogTable whose TablePath.getDatabaseName() returns null is passed to VitessSourceConfig.of — e.g. table paths built from bare table names without keyspace/database qualification, or upstream metadata that omits the database part.","commonSituations":"Configuring tables as 'tablename' instead of 'keyspace.tablename'; catalog tools emitting unqualified paths; programmatic job construction building TablePath with only the table name.","solutions":["Qualify every table with its keyspace/database, e.g. 'commerce.orders' instead of 'orders'","Fix the code that constructs TablePath to include the database name","Ensure upstream catalog resolution preserves the database component of the path","Validate table paths before building the source config"],"exampleFix":"// before\nTablePath path = TablePath.of(null, \"orders\");\n// after\nTablePath path = TablePath.of(\"commerce\", \"orders\"); // keyspace-qualified","handlingStrategy":"validation","validationCode":"for (CatalogTable t : catalogTables) {\n    if (t.getTablePath().getDatabaseName() == null) {\n        throw new IllegalArgumentException(\"Table path \" + t.getTablePath() + \" must be keyspace-qualified, e.g. commerce.orders\");\n    }\n}","typeGuard":"static boolean isDatabaseQualified(CatalogTable t) {\n    return t.getTablePath() != null && t.getTablePath().getDatabaseName() != null;\n}","tryCatchPattern":"try {\n    cfg = VitessSourceConfig.of(options, catalogTables);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"database-qualified table paths\")) {\n        LOG.error(\"Qualify every table with its keyspace: keyspace.table\");\n    }\n    throw e;\n}","preventionTips":["Always write table config entries as keyspace.table","Normalize TablePath construction to require the database component","Validate table paths at config-load time, before catalog resolution"],"tags":["vitess","cdc","table-path","config","naming"],"backgroundTag":"missing-required-argument","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"}