knex/knex · error · Error
.onConflict() is not supported for oracledb.
Error message
.onConflict() is not supported for oracledb.
What it means
QueryCompiler_Oracle's constructor inspects this.single.onConflict and immediately throws if set. The legacy oracle dialect never implemented ON CONFLICT upserts, so any onConflict in the builder fails fast at compile time. Note the message says 'oracledb' even though this lives in the oracle dialect folder. Thrown the moment the compiler is constructed for the query.
Source
Thrown at lib/dialects/oracle/query/oracle-querycompiler.js:38
'group',
'having',
'order',
'lock',
];
// Query Compiler
// -------
// Set the "Formatter" to use for the queries,
// ensuring that all parameterized values (even across sub-queries)
// are properly built into the same query.
class QueryCompiler_Oracle extends QueryCompiler {
constructor(client, builder, formatter) {
super(client, builder, formatter);
const { onConflict } = this.single;
if (onConflict) {
throw new Error('.onConflict() is not supported for oracledb.');
}
// Compiles the `select` statement, or nested sub-selects
// by calling each of the component compilers, trimming out
// the empties, and returning a generated query string.
this.first = this.select;
}
// Compiles an "insert" query, allowing for multiple
// inserts using a single query statement.
insert() {
let insertValues = this.single.insert || [];
let { returning } = this.single;
if (!Array.isArray(insertValues) && isPlainObject(this.single.insert)) {
insertValues = [this.single.insert];
}
View on GitHub (pinned to e25d54bcb7)
Solutions
- Switch the client to 'oracledb' (the modern driver) which has broader upsert support, or
- Rewrite the upsert using Oracle's MERGE INTO ... WHEN MATCHED via knex.raw.
- Branch the upsert code path by dialect so oracle uses MERGE instead of onConflict.
Example fix
// before
await knex('users')
.insert({ id: 1, email: 'a@b.c' })
.onConflict('id').merge();
// after (Oracle MERGE)
await knex.raw(`
MERGE INTO users d
USING (SELECT 1 AS id, 'a@b.c' AS email FROM dual) s
ON (d.id = s.id)
WHEN MATCHED THEN UPDATE SET d.email = s.email
WHEN NOT MATCHED THEN INSERT (id, email) VALUES (s.id, s.email)
`); Defensive patterns
Strategy: validation
Validate before calling
// Reject onConflict at build time for the oracle dialect with a helpful message.
function assertNoOnConflictForOracle(knex) {
if (knex.client.driverName === 'oracle') {
throw new Error('onConflict is unsupported on the legacy oracle driver — use MERGE INTO or the oracledb client.');
}
}
// call before .onConflict in shared upsert helpers Type guard
function supportsOnConflict(driverName) {
return !['oracle'].includes(driverName);
} Try / catch
try {
await knex('users').insert(row).onConflict('id').merge();
} catch (e) {
if (/onConflict\(\) is not supported for oracledb/i.test(e.message)) {
await knex.raw(`MERGE INTO users d USING (SELECT :id AS id, :email AS email FROM dual) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE SET d.email = s.email WHEN NOT MATCHED THEN INSERT (id, email) VALUES (s.id, s.email)`, row);
} else throw e;
} Prevention
- Prefer the modern 'oracledb' client over legacy 'oracle'.
- Implement upserts via MERGE INTO for Oracle instead of onConflict.
- Branch shared query helpers by dialect.
When it happens
Trigger: Using .onConflict(column) (in any chaining form — ignore, merge, or with updates) on a query built against the legacy 'oracle' client. The throw happens before any merge/ignore logic since it checks onConflict presence directly.
Common situations: Switching a codebase from Postgres to Oracle and assuming onConflict is portable; shared model layer that uses upserts; migrating from the oracledb dialect (which may handle some cases) to the older oracle driver.
Related errors
- .onConflict().merge().where() is not supported for mysql
- If using merge with a raw insert query, then updates must be
- .dropUniqueIfExists() is not supported by oracle
- .dropForeignIfExists() is not supported by oracle
- .dropPrimaryIfExists() is not supported by oracle
AI-assisted analysis of knex/knex@e25d54bcb7 (2026-08-03).
Data as JSON: /data/errors/46af3f5685f7f02d.json.
Report an issue: GitHub.