n8n-io/n8n · error · ReturningStatementNotSupportedError
OUTPUT or RETURNING clause only supported by Microsoft SQL S
Error message
OUTPUT or RETURNING clause only supported by Microsoft SQL Server or PostgreSQL or MariaDB databases.
What it means
DeleteQueryBuilder.returning() calls connection.driver.isReturningSqlSupported('delete') and throws ReturningStatementNotSupportedError when it returns false. RETURNING (Postgres) / OUTPUT (SQL Server) lets a DELETE return deleted columns, but drivers like older MySQL, Oracle, SAP HANA, and some SQLite configurations reject it. The guard runs at build configuration time, before any SQL is sent.
Source
Thrown at packages/@n8n/typeorm/src/query-builder/DeleteQueryBuilder.ts:237
/**
* Optional returning/output clause.
* Returning is a SQL string containing returning statement.
*/
returning(returning: string): this;
/**
* Optional returning/output clause.
*/
returning(returning: string | string[]): this;
/**
* Optional returning/output clause.
*/
returning(returning: string | string[]): this {
// not all databases support returning/output cause
if (!this.connection.driver.isReturningSqlSupported('delete')) {
throw new ReturningStatementNotSupportedError();
}
this.expressionMap.returning = returning;
return this;
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------
/**
* Creates DELETE express used to perform query.
*/
protected createDeleteExpression() {
const tableName = this.getTableName(this.getMainTableName());
const whereExpression = this.createWhereExpression();
const returningExpression = this.createReturningExpression('delete');
View on GitHub (pinned to 5ac6606e81)
Solutions
- Guard the .returning() call with a driver capability check: if (dataSource.driver.isReturningSqlSupported('delete')).
- Drop .returning() and issue a follow-up SELECT by id before delete, or capture affected ids another way.
- If you need DELETE ... RETURNING universally, use Postgres, SQL Server, or modern SQLite as the backing database.
- Factor driver-specific delete logic behind a repository strategy that branches on connection.options.type.
Example fix
// before
const res = await dataSource
.createQueryBuilder().delete()
.from(User).where('id = :id', { id })
.returning(['id', 'email']).execute(); // throws on MySQL
// after
if (dataSource.driver.isReturningSqlSupported('delete')) {
return dataSource.createQueryBuilder().delete().from(User)
.where('id = :id', { id }).returning(['id', 'email']).execute();
}
const existing = await dataSource.getRepository(User).findOne({ where: { id } });
await dataSource.getRepository(User).delete(id);
return existing; Defensive patterns
Strategy: validation
Validate before calling
function supportsDeleteReturning(ds: DataSource): boolean {
return ds.driver.isReturningSqlSupported('delete');
}
if (!supportsDeleteReturning(dataSource)) { /* fall back to select-before-delete */ } Type guard
function supportsReturning(driver: import('../driver/Driver').Driver, op: 'insert'|'update'|'delete'): boolean {
return driver.isReturningSqlSupported(op);
} Try / catch
try {
return qb.delete().from(E).where(...).returning(cols).execute();
} catch (e) {
if (e instanceof ReturningStatementNotSupportedError) { /* select-before-delete fallback */ }
throw e;
} Prevention
- Check driver.isReturningSqlSupported('delete') before .returning().
- Prefer repository.delete(id) for portable code.
- Keep driver-specific RETURNING paths behind a strategy that branches on connection.options.type.
- Document which DBs each code path supports in the feature module.
When it happens
Trigger: Calling .returning(['id']).delete().from(Entity).execute() (or delete().returning(...)) against a driver whose isReturningSqlSupported('delete') is false. Determined by the driver class: MssqlDriver and Postgres/AuroraPostgres return true; better-sqlite3 with 'enable-wal' may; MongoDriver, OracleDriver, MysqlDriver (pre-8 for some paths), SapDriver do not.
Common situations: Writing portable code against SQLite/MySQL in dev and Postgres in CI. Copying a Postgres RETURNING pattern into a feature that must run on MySQL/MariaDB. Forgetting that MongoDB driver is fundamentally non-relational.
Related errors
- OUTPUT or RETURNING clause only supported by Microsoft SQL S
- indexPredicate option is not supported by the current databa
- onUpdate is not supported by the current database driver
- Only select queries are supported in CTEs in ${this.connecti
- Cannot get entity metadata for the given alias "${this.name}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/e84c7c07ee4b92f8.
Report an issue: GitHub.