{"record":{"id":"cef93b29fcfacac6","repo":"apache/seatunnel","slug":"oracle-insert-mode-append-values-only-supports-ins","errorCode":null,"errorMessage":"oracle_insert_mode=APPEND_VALUES only supports insert-only writes without primary keys.","messagePattern":"oracle_insert_mode=APPEND_VALUES only supports insert-only writes without primary keys\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/JdbcOutputFormatBuilder.java","lineNumber":384,"sourceCode":"                    \"oracle_insert_mode=APPEND_VALUES only supports generated INSERT statements.\");\n        }\n        String appendValuesSQL =\n                insertPrefix + \" /*+ APPEND_VALUES */\" + insertSQL.substring(insertPrefix.length());\n        log.info(\"Oracle APPEND_VALUES insert mode is enabled, generated SQL: {}\", appendValuesSQL);\n        return appendValuesSQL;\n    }\n\n    private static void validateOracleInsertMode(\n            JdbcDialect dialect, JdbcSinkConfig jdbcSinkConfig, List<String> primaryKeys) {\n        if (!isOracleAppendValuesConfigured(jdbcSinkConfig)) {\n            return;\n        }\n        if (!DatabaseIdentifier.ORACLE.equals(dialect.dialectName())) {\n            throw new IllegalArgumentException(\n                    \"oracle_insert_mode=APPEND_VALUES only supports Oracle JDBC sink.\");\n        }\n        if (primaryKeys != null && !primaryKeys.isEmpty()) {\n            throw new IllegalArgumentException(\n                    \"oracle_insert_mode=APPEND_VALUES only supports insert-only writes without primary keys.\");\n        }\n    }\n\n    private static boolean isOracleAppendValuesConfigured(JdbcSinkConfig jdbcSinkConfig) {\n        return JdbcSinkConfig.OracleInsertMode.APPEND_VALUES.equals(\n                jdbcSinkConfig.getOracleInsertMode());\n    }\n\n    static Function<SeaTunnelRow, SeaTunnelRow> createKeyExtractor(int[] pkFields) {\n        return row -> {\n            Object[] fields = new Object[pkFields.length];\n            for (int i = 0; i < pkFields.length; i++) {\n                fields[i] = row.getField(pkFields[i]);\n            }\n            SeaTunnelRow newRow = new SeaTunnelRow(fields);\n            newRow.setTableId(row.getTableId());\n            return newRow;","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/JdbcOutputFormatBuilder.java#L366-L402","documentation":"Thrown by JdbcOutputFormatBuilder.validateOracleInsertMode when oracle_insert_mode=APPEND_VALUES is configured on an Oracle sink but primary keys are present. APPEND_VALUES is only valid for insert-only writes; primary-key presence implies upsert/merge semantics which cannot use the hint.","triggerScenarios":"Config sets oracle_insert_mode=APPEND_VALUES and the sink resolves a non-empty primary key list (from schema or config).","commonSituations":"Table has a primary key and SeaTunnel auto-detects it; user expects APPEND_VALUES to work with keyed writes; copying configs between keyed and non-keyed tables.","solutions":["Remove or set oracle_insert_mode back to INSERT if the target table has primary keys","Drop the primary_keys entry in the sink config if writes are truly append-only","Use Oracle's native MERGE/upsert path instead of APPEND_VALUES for keyed writes"],"exampleFix":"// before\nprimary_keys = [\"id\"]\noracle_insert_mode = \"APPEND_VALUES\"\n// after\noracle_insert_mode = \"INSERT\"","handlingStrategy":"validation","validationCode":"// APPEND_VALUES requires no primary keys\nif (\"APPEND_VALUES\".equals(config.get(\"oracle_insert_mode\")) && primaryKeys != null && !primaryKeys.isEmpty()) {\n  throw new IllegalArgumentException(\"APPEND_VALUES cannot be used with primary keys\");\n}","typeGuard":null,"tryCatchPattern":"try { builder.build(); } catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"insert-only\")) { /* switch to default insert mode */ }\n}","preventionTips":["Use APPEND_VALUES only for append-only, key-less tables","Remove primary_keys from sink config for pure inserts","For keyed/upsert writes use the dialect's upsert support instead"],"tags":["oracle","jdbc","config","primary-key"],"backgroundTag":"conflicting-config-options","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}