apache/beam · error · IllegalArgumentException
Write Statement and Table are mutually exclusive configurati
Error message
Write Statement and Table are mutually exclusive configurations
What it means
JdbcWriteSchemaTransformConfiguration supports writing either a custom write statement OR a table (given via location), but not both. Supplying both is ambiguous, so validate() throws this IllegalArgumentException.
Source
Thrown at sdks/java/io/jdbc/src/main/java/org/apache/beam/sdk/io/jdbc/JdbcWriteSchemaTransformProvider.java:416
throw new IllegalArgumentException(
"If JDBC type is not specified, then Driver Class Name and Driver Jars must be specified.");
}
if (!driverClassNamePresent && !jdbcTypePresent) {
throw new IllegalArgumentException(
"One of JDBC Driver class name or JDBC type must be specified.");
}
if (jdbcTypePresent
&& !JDBC_DRIVER_MAP.containsKey(Objects.requireNonNull(jdbcType).toLowerCase())) {
throw new IllegalArgumentException(
"JDBC type must be one of " + JDBC_DRIVER_MAP.keySet() + " but was " + jdbcType);
}
boolean writeStatementPresent =
(getWriteStatement() != null && !"".equals(getWriteStatement()));
boolean locationPresent = (getLocation() != null && !"".equals(getLocation()));
if (writeStatementPresent && locationPresent) {
throw new IllegalArgumentException(
"Write Statement and Table are mutually exclusive configurations");
}
if (!writeStatementPresent && !locationPresent) {
throw new IllegalArgumentException("Either Write Statement or Table must be set.");
}
}
public static Builder builder() {
return new AutoValue_JdbcWriteSchemaTransformProvider_JdbcWriteSchemaTransformConfiguration
.Builder();
}
public abstract Builder toBuilder();
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setDriverClassName(String value);
View on GitHub (pinned to 12126d8942)
Solutions
- Remove setWriteStatement(...) and keep setLocation(table) for a plain table insert
- Or remove setLocation(...) and keep the custom write statement
- Decide the write mode in code: if statement != null, skip setting location
Example fix
// before
builder().setJdbcUrl(url).setLocation("orders").setWriteStatement("INSERT INTO orders VALUES(?)").build();
// after
builder().setJdbcUrl(url).setWriteStatement("INSERT INTO orders VALUES(?)").build(); Defensive patterns
Strategy: validation
Validate before calling
if (cfg.getWriteStatement() != null && !cfg.getWriteStatement().isEmpty()
&& cfg.getLocation() != null && !cfg.getLocation().isEmpty()) {
throw new IllegalArgumentException("Set either writeStatement or location, not both");
} Try / catch
try {
config.validate();
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("mutually exclusive")) {
LOG.error("Drop either writeStatement or location from the config");
}
throw e;
} Prevention
- Pick one write mode per configuration object; never merge templates blindly
- When deriving config from parameters, set location only if statement is absent
When it happens
Trigger: Setting both setWriteStatement(...) and setLocation(...) on the configuration before validate().
Common situations: Merging configs where a template already contains a write statement and the user also sets the target table; scripted config assembly appending both fields unconditionally.
Related errors
- JDBC URL cannot be blank
- If JDBC type is not specified, then Driver Class Name and Dr
- One of JDBC Driver class name or JDBC type must be specified
- JDBC type must be one of ${JDBC_DRIVER_MAP.keySet()} but was
- Either Write Statement or Table must be set.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5cd3ad44a8d668d8.
Report an issue: GitHub.