apache/seatunnel · error · IllegalArgumentException

oracle_insert_mode=APPEND_VALUES only supports Oracle JDBC s

Error message

oracle_insert_mode=APPEND_VALUES only supports Oracle JDBC sink.

What it means

Thrown by JdbcOutputFormatBuilder.validateOracleInsertMode when oracle_insert_mode=APPEND_VALUES is configured but the active JDBC dialect is not Oracle. The APPEND_VALUES hint is Oracle-specific syntax and is meaningless (and invalid) on other databases, so the builder rejects the combination early.

Source

Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/JdbcOutputFormatBuilder.java:380

        }
        final String insertPrefix = "INSERT";
        if (!insertSQL.regionMatches(true, 0, insertPrefix, 0, insertPrefix.length())) {
            throw new IllegalArgumentException(
                    "oracle_insert_mode=APPEND_VALUES only supports generated INSERT statements.");
        }
        String appendValuesSQL =
                insertPrefix + " /*+ APPEND_VALUES */" + insertSQL.substring(insertPrefix.length());
        log.info("Oracle APPEND_VALUES insert mode is enabled, generated SQL: {}", appendValuesSQL);
        return appendValuesSQL;
    }

    private static void validateOracleInsertMode(
            JdbcDialect dialect, JdbcSinkConfig jdbcSinkConfig, List<String> primaryKeys) {
        if (!isOracleAppendValuesConfigured(jdbcSinkConfig)) {
            return;
        }
        if (!DatabaseIdentifier.ORACLE.equals(dialect.dialectName())) {
            throw new IllegalArgumentException(
                    "oracle_insert_mode=APPEND_VALUES only supports Oracle JDBC sink.");
        }
        if (primaryKeys != null && !primaryKeys.isEmpty()) {
            throw new IllegalArgumentException(
                    "oracle_insert_mode=APPEND_VALUES only supports insert-only writes without primary keys.");
        }
    }

    private static boolean isOracleAppendValuesConfigured(JdbcSinkConfig jdbcSinkConfig) {
        return JdbcSinkConfig.OracleInsertMode.APPEND_VALUES.equals(
                jdbcSinkConfig.getOracleInsertMode());
    }

    static Function<SeaTunnelRow, SeaTunnelRow> createKeyExtractor(int[] pkFields) {
        return row -> {
            Object[] fields = new Object[pkFields.length];
            for (int i = 0; i < pkFields.length; i++) {
                fields[i] = row.getField(pkFields[i]);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove the oracle_insert_mode option if the target is not Oracle
  2. Switch the dialect/driver back to Oracle if Oracle was intended
  3. Use the dialect's own bulk-load/optimization options for the non-Oracle database

Example fix

// before
url = "jdbc:mysql://host/db"
oracle_insert_mode = "APPEND_VALUES"
// after
url = "jdbc:mysql://host/db"
Defensive patterns

Strategy: validation

Validate before calling

// ensure option matches dialect
if (config.get("oracle_insert_mode") != null && !dialectName.equals("oracle")) {
  throw new IllegalArgumentException("oracle_insert_mode is Oracle-only");
}

Try / catch

try { builder.build(); } catch (IllegalArgumentException e) {
  if (e.getMessage().contains("only supports Oracle")) { /* remove option and rebuild */ }
}

Prevention

When it happens

Trigger: Config contains oracle_insert_mode=APPEND_VALUES while dialect/dialectName() is not ORACLE — e.g. driver set to MySQL, PostgreSQL, etc.

Common situations: Copying an Oracle sink config template to another database; generic driver selection where the Oracle-only option was left enabled.

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/53bbf634b47cf89b. Report an issue: GitHub.