{"record":{"id":"3c42b7507a69fd47","repo":"n8n-io/n8n","slug":"indexpredicate-option-is-not-supported-by-the-curr","errorCode":null,"errorMessage":"indexPredicate option is not supported by the current database driver","messagePattern":"indexPredicate option is not supported by the current database driver","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/InsertQueryBuilder.ts","lineNumber":400,"sourceCode":"\t\t} else {\n\t\t\tquery += ` DEFAULT VALUES`;\n\t\t}\n\t\tif (this.expressionMap.onUpdate?.upsertType !== 'primary-key') {\n\t\t\tif (this.connection.driver.supportedUpsertTypes.includes('on-conflict-do-update')) {\n\t\t\t\tif (this.expressionMap.onIgnore) {\n\t\t\t\t\tquery += ' ON CONFLICT DO NOTHING ';\n\t\t\t\t} else if (this.expressionMap.onConflict) {\n\t\t\t\t\tquery += ` ON CONFLICT ${this.expressionMap.onConflict} `;\n\t\t\t\t} else if (this.expressionMap.onUpdate) {\n\t\t\t\t\tconst { overwrite, columns, conflict, skipUpdateIfNoValuesChanged, indexPredicate } =\n\t\t\t\t\t\tthis.expressionMap.onUpdate;\n\n\t\t\t\t\tlet conflictTarget = 'ON CONFLICT';\n\n\t\t\t\t\tif (Array.isArray(conflict)) {\n\t\t\t\t\t\tconflictTarget += ` ( ${conflict.map((column) => this.escape(column)).join(', ')} )`;\n\t\t\t\t\t\tif (indexPredicate && !DriverUtils.isPostgresFamily(this.connection.driver)) {\n\t\t\t\t\t\t\tthrow new TypeORMError(\n\t\t\t\t\t\t\t\t`indexPredicate option is not supported by the current database driver`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (indexPredicate && DriverUtils.isPostgresFamily(this.connection.driver)) {\n\t\t\t\t\t\t\tconflictTarget += ` WHERE ( ${indexPredicate} )`;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (conflict) {\n\t\t\t\t\t\tconflictTarget += ` ON CONSTRAINT ${this.escape(conflict)}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst updatePart: string[] = [];\n\n\t\t\t\t\tif (Array.isArray(overwrite)) {\n\t\t\t\t\t\tupdatePart.push(\n\t\t\t\t\t\t\t...overwrite.map(\n\t\t\t\t\t\t\t\t(column) => `${this.escape(column)} = EXCLUDED.${this.escape(column)}`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/InsertQueryBuilder.ts#L382-L418","documentation":"In InsertQueryBuilder.createConflictExpression(), when onUpdate.conflict is a column array and onUpdate.indexPredicate is set, the code checks DriverUtils.isPostgresFamily(driver). Only Postgres-family drivers support a partial-index predicate (ON CONFLICT (col) WHERE predicate DO UPDATE). On any other driver the predicate is meaningless and TypeORMError is thrown at query build time.","triggerScenarios":"Calling .orUpdate({ conflict: ['email'], overwrite: ['name'], indexPredicate: 'deleted_at IS NULL' }) on an upsert against SQLite, MySQL, CockroachDB-non-pg-path, or any non-Postgres driver. The conflict target is an array (column list) which is the branch that even evaluates indexPredicate.","commonSituations":"Developing upsert logic on Postgres locally then deploying to MySQL/SQLite. Using a partial unique index's predicate that only exists in Postgres. Copying a Postgres ON CONFLICT ... WHERE clause into a driver-portable code path.","solutions":["Remove indexPredicate from orUpdate options when targeting non-Postgres drivers.","Branch on DriverUtils.isPostgresFamily(dataSource.driver) and only pass indexPredicate in the Postgres branch.","Ensure the partial index actually exists in the Postgres schema before referencing its predicate.","Use the 'primary-key' upsertType path or onConflict string if you need driver-portable behavior."],"exampleFix":"// before\nawait dataSource.createQueryBuilder()\n  .insert().into(User).values(payload)\n  .orUpdate({\n    conflict: ['email'],\n    overwrite: ['name'],\n    indexPredicate: 'deleted_at IS NULL', // throws on SQLite/MySQL\n  }).execute();\n\n// after\nconst isPg = DriverUtils.isPostgresFamily(dataSource.driver);\nawait dataSource.createQueryBuilder()\n  .insert().into(User).values(payload)\n  .orUpdate({\n    conflict: ['email'],\n    overwrite: ['name'],\n    ...(isPg ? { indexPredicate: 'deleted_at IS NULL' } : {}),\n  }).execute();","handlingStrategy":"validation","validationCode":"import { DriverUtils } from '@n8n/typeorm/driver/DriverUtils';\nfunction safeOrUpdateOptions(ds: DataSource, opts: { conflict: string[]; overwrite: string[]; indexPredicate?: string }) {\n  const isPg = DriverUtils.isPostgresFamily(ds.driver);\n  return { ...opts, ...(isPg && opts.indexPredicate ? { indexPredicate: opts.indexPredicate } : {}) };\n}","typeGuard":"function isPostgresFamily(ds: DataSource): boolean {\n  return DriverUtils.isPostgresFamily(ds.driver);\n}","tryCatchPattern":null,"preventionTips":["Only set indexPredicate when DriverUtils.isPostgresFamily(driver) is true.","Centralize upsert-option construction behind a helper that strips Postgres-only fields.","Document which orUpdate options are Postgres-only.","Test upsert paths against SQLite/MySQL in CI, not just Postgres."],"tags":["query-builder","insert","upsert","postgres","driver-capability"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}