apache/beam · error · IllegalArgumentException

Either Write Statement or Table must be set.

Error message

Either Write Statement or Table must be set.

What it means

The inverse of the mutual-exclusion check: the provider requires at least one write target. If neither a write statement nor a table location is set, validate() throws this IllegalArgumentException because it has nothing to write to.

Source

Thrown at sdks/java/io/jdbc/src/main/java/org/apache/beam/sdk/io/jdbc/JdbcWriteSchemaTransformProvider.java:420

        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);

      public abstract Builder setJdbcType(String value);

      public abstract Builder setJdbcUrl(String value);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Set setLocation("table_name") for a straightforward table write
  2. Or set setWriteStatement("INSERT INTO ... VALUES(?)") for custom SQL
  3. If the target comes from parameters, validate it is non-empty before building the config

Example fix

// before
builder().setJdbcUrl(url).setJdbcType("postgres").build();
// after
builder().setJdbcUrl(url).setJdbcType("postgres").setLocation("my_table").build();
Defensive patterns

Strategy: validation

Validate before calling

boolean stmt = cfg.getWriteStatement() != null && !cfg.getWriteStatement().isEmpty();
boolean loc = cfg.getLocation() != null && !cfg.getLocation().isEmpty();
if (!stmt && !loc) {
  throw new IllegalArgumentException("Set writeStatement or location (table)");
}

Try / catch

try {
  config.validate();
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Either Write Statement or Table must be set")) {
    LOG.error("Configure a write target: table (location) or custom write statement");
  }
  throw e;
}

Prevention

When it happens

Trigger: Building JdbcWriteSchemaTransformConfiguration with jdbcUrl/driver info only and calling validate() — no setWriteStatement and no setLocation.

Common situations: Incomplete config assembly where the target table is derived from a variable that was empty; template configs where the table placeholder never got substituted.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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