apache/beam · error · IllegalArgumentException

If JDBC type is not specified, then Driver Class Name and…

Error message

If JDBC type is not specified, then Driver Class Name and Driver Jars must be specified.

What it means

The JdbcReadSchemaTransformProvider validator requires enough information to pick a JDBC driver. If none of jdbcType, driverClassName, or driverJars is present, it cannot load a driver and throws this IllegalArgumentException immediately after the URL check.

Solutions

  1. Set jdbcType to a supported value from JDBC_DRIVER_MAP (e.g. mysql, postgresql, oracle, mssql).
  2. Or set driverClassName (e.g. com.mysql.cj.jdbc.Driver) together with driverJars pointing to the driver artifact.
  3. Check the serialized config map keys for typos like driverClass vs driverClassName.

Example fix

// before
builder().setJdbcUrl(url).setLocation("table1")
// after
builder().setJdbcUrl(url).setLocation("table1").setJdbcType("postgresql")
Defensive patterns

Strategy: validation

Validate before calling

boolean hasType = config.getJdbcType() != null && !config.getJdbcType().isEmpty();
boolean hasDriver = (config.getDriverClassName() != null && !config.getDriverClassName().isEmpty())
    && (config.getDriverJars() != null && !config.getDriverJars().isEmpty());
if (!hasType && !hasDriver) {
  throw new IllegalArgumentException("Set either jdbcType or driverClassName+driverJars");
}

Try / catch

try {
  config.validate();
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("If JDBC type is not specified")) {
    throw new IllegalStateException("Driver configuration missing: set jdbcType or driverClassName+driverJars", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling validate() (directly, via from(), or from SqlServerReadSchemaTransform) with a configuration where jdbcType is null/empty AND driverClassName is null/empty AND driverJars is null/empty.

Common situations: Users new to the SchemaTransform API provide only URL/query/location and expect the driver to be auto-detected; config migration dropped the driver fields.

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/96748ad096af3634. Report an issue: GitHub.

Appendix: source

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

    @Nullable
    public abstract String getUsername();

    public void validate() {
      validate("");
    }

    public void validate(String jdbcType) throws IllegalArgumentException {
      if (Strings.isNullOrEmpty(getJdbcUrl())) {
        throw new IllegalArgumentException("JDBC URL cannot be blank");
      }

      jdbcType = !Strings.isNullOrEmpty(jdbcType) ? jdbcType : getJdbcType();

      boolean driverClassNamePresent = !Strings.isNullOrEmpty(getDriverClassName());
      boolean driverJarsPresent = !Strings.isNullOrEmpty(getDriverJars());
      boolean jdbcTypePresent = !Strings.isNullOrEmpty(jdbcType);
      if (!driverClassNamePresent && !driverJarsPresent && !jdbcTypePresent) {
        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());
      }

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

View on GitHub (pinned to 12126d8942)