apache/seatunnel · error · OptionValidationException
root-level 'schema' cannot be used with 'tables_configs'
Error message
root-level 'schema' cannot be used with 'tables_configs'
What it means
Neo4jSourceFactory disallows combining a root-level 'schema' option with 'tables_configs'. The two are mutually exclusive configuration modes: root-level query+schema defines a single table, while tables_configs defines multiple tables each with their own query and schema. A root-level schema alongside tables_configs is ambiguous and rejected with OptionValidationException.
Solutions
- Remove the root-level 'schema' option when using 'tables_configs'; each entry must carry its own schema.
- If you only have one table, remove 'tables_configs' and keep the root-level 'query' + 'schema' instead.
- Move column/table definitions from the root schema into each tables_configs entry's schema.
Example fix
// before
source {
Neo4j {
uri = "bolt://localhost:7687"
schema = { table = "person", columns = [...] }
tables_configs = [
{ query = "MATCH (n:Person) RETURN ...", schema = { table = "person", ... } }
]
}
}
// after
source {
Neo4j {
uri = "bolt://localhost:7687"
tables_configs = [
{ query = "MATCH (n:Person) RETURN ...", schema = { table = "person", columns = [...] } }
]
}
} Defensive patterns
Strategy: validation
Validate before calling
if (config.hasPath("schema") && config.hasPath("tables_configs")) {
throw new IllegalArgumentException("use either root-level schema or tables_configs, not both");
} Prevention
- Pick one mode: single-table (root query+schema) or multi-table (tables_configs).
- When migrating configs, delete the old root-level schema after moving definitions into entries.
- Keep config templates per mode to avoid mixing.
When it happens
Trigger: Calling evaluate(ReadonlyConfig, List) during validation when the config contains both ConnectorCommonOptions.SCHEMA at the root and a non-empty 'tables_configs' list.
Common situations: Users incrementally migrate a single-query config to multi-table config and leave the old root-level schema in place; templated configs merge root-level defaults (schema) with per-table entries.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- 'schema' must be configured when using a root-level 'query'
- Stripe option 'created_gte' must be less than 'created_lt'
- tables_configs[ ]: duplicate 'schema.table' value
- tables_configs[ ]: 'query' must be configured and non-blank
- tables_configs[ ]: 'schema' must be configured and non-empty
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b3137e122da18064.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-neo4j/src/main/java/org/apache/seatunnel/connectors/seatunnel/neo4j/source/Neo4jSourceFactory.java:196
throw new OptionValidationException(
"'schema' must be configured when using a root-level 'query'");
}
return true;
}
}
static class TableConfigsValidator implements ConditionExtension<List<Map<String, Object>>> {
@Override
public String description() {
return "each 'tables_configs' entry must contain a non-blank 'query' and a schema with a unique 'table'";
}
@Override
public boolean evaluate(ReadonlyConfig config, List<Map<String, Object>> entries)
throws OptionValidationException {
if (config.getOptional(ConnectorCommonOptions.SCHEMA).isPresent()) {
throw new OptionValidationException(
"root-level 'schema' cannot be used with 'tables_configs'");
}
Set<String> tableIds = new HashSet<>();
for (int i = 0; i < entries.size(); i++) {
Map<String, Object> entry = entries.get(i);
Object query = entry.get(Neo4jSourceOptions.KEY_QUERY.key());
if (!(query instanceof String) || ((String) query).trim().isEmpty()) {
throw new OptionValidationException(
"tables_configs[%d]: 'query' must be configured and non-blank", i);
}
Object schemaValue = entry.get(ConnectorCommonOptions.SCHEMA.key());
if (!(schemaValue instanceof Map) || ((Map<?, ?>) schemaValue).isEmpty()) {
throw new OptionValidationException(
"tables_configs[%d]: 'schema' must be configured and non-empty", i);
}
View on GitHub (pinned to cf67b549a7)