apache/beam · error · IllegalArgumentException

Query and Table are mutually exclusive configurations

Error message

Query and Table are mutually exclusive configurations

What it means

The JdbcReadSchemaTransformConfiguration treats readQuery and location (table) as alternatives: a query replaces the table source. If both readQuery and location are set, validate() throws this IllegalArgumentException because the intent is ambiguous.

Solutions

  1. Remove setLocation() if you want to read with a custom SQL query.
  2. Remove setReadQuery() if you want to read a whole table (required for partitioned reads).
  3. Centralize config assembly so only one of the two fields is ever populated.

Example fix

// before
builder().setJdbcUrl(url).setLocation("t1").setReadQuery("SELECT * FROM t1")
// after
builder().setJdbcUrl(url).setReadQuery("SELECT * FROM t1") // drop the table
Defensive patterns

Strategy: validation

Validate before calling

if (hasText(config.getReadQuery()) && hasText(config.getLocation())) {
  throw new IllegalArgumentException("Set either readQuery or location (table), not both");
}

Try / catch

try {
  config.validate();
} catch (IllegalArgumentException e) {
  if ("Query and Table are mutually exclusive configurations".equals(e.getMessage())) {
    throw new IllegalStateException("Config contains both readQuery and table; keep only one", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Building the transform with both setReadQuery(...) and setLocation(...) (table) non-empty and then calling from()/validate().

Common situations: Merging default config templates that each populate one field, or UIs that persist the last-selected option without clearing the other.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/9695483da2e9d494. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/jdbc/src/main/java/org/apache/beam/sdk/io/jdbc/JdbcReadSchemaTransformProvider.java:432

            "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());
      }

      boolean readQueryPresent = (getReadQuery() != null && !"".equals(getReadQuery()));
      boolean locationPresent = (getLocation() != null && !"".equals(getLocation()));
      boolean partitionColumnPresent =
          (getPartitionColumn() != null && !"".equals(getPartitionColumn()));

      // If you specify a readQuery, it is to be used instead of a table.
      if (readQueryPresent && locationPresent) {
        throw new IllegalArgumentException("Query and Table are mutually exclusive configurations");
      }
      if (!readQueryPresent && !locationPresent) {
        throw new IllegalArgumentException("Either Query or Table must be specified.");
      }
      // Reading with partitions only supports table argument.
      if (partitionColumnPresent && !locationPresent) {
        throw new IllegalArgumentException("Table must be specified to read with partitions.");
      }
    }

    public static Builder builder() {
      return new AutoValue_JdbcReadSchemaTransformProvider_JdbcReadSchemaTransformConfiguration
          .Builder();
    }

    public abstract Builder toBuilder();

    @AutoValue.Builder

View on GitHub (pinned to 12126d8942)