n8n-io/n8n · error · TypeORMError

OnDeleteType "${relation.onDelete}" is not supported for ${d

Error message

OnDeleteType "${relation.onDelete}" is not supported for ${driver.options.type}!

What it means

Thrown by EntityMetadataValidator.validate during the relations loop when a relation declares an onDelete option whose value is not in driver.supportedOnDeleteTypes for the active database. The guard requires driver.supportedOnDeleteTypes to be set, relation.onDelete to be set, and includes() to be false to throw.

Source

Thrown at packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts:160

			if (relation.isManyToMany || relation.isOneToMany) {
				// we skip relations for which persistence is disabled since initialization in them cannot harm somehow
				if (relation.persistenceEnabled === false) return;

				// get entity relation value and check if its an array
				const relationInitializedValue = relation.getEntityValue(entityInstance);
				if (Array.isArray(relationInitializedValue)) throw new InitializedRelationError(relation);
			}
		});

		// validate relations
		entityMetadata.relations.forEach((relation) => {
			// check OnDeleteTypes
			if (
				driver.supportedOnDeleteTypes &&
				relation.onDelete &&
				!driver.supportedOnDeleteTypes.includes(relation.onDelete)
			) {
				throw new TypeORMError(
					`OnDeleteType "${relation.onDelete}" is not supported for ${driver.options.type}!`,
				);
			}

			// check OnUpdateTypes
			if (
				driver.supportedOnUpdateTypes &&
				relation.onUpdate &&
				!driver.supportedOnUpdateTypes.includes(relation.onUpdate)
			) {
				throw new TypeORMError(
					`OnUpdateType "${relation.onUpdate}" is not valid for ${driver.options.type}!`,
				);
			}

			// check join tables:
			// using JoinTable is possible only on one side of the many-to-many relation
			// todo(dima): fix

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Use a value listed in driver.supportedOnDeleteTypes for your database (typically 'RESTRICT' | 'SET NULL' | 'CASCADE' | 'NO ACTION' | 'DEFAULT').
  2. If the driver (e.g. SQLite) does not support the action, drop onDelete or pick one it supports.
  3. Centralize referential-action strings in a shared const enum to prevent typos.

Example fix

// before
@ManyToOne(() => User, (u) => u.posts, { onDelete: 'RESTRICTED' })
author: User;

// after
@ManyToOne(() => User, (u) => u.posts, { onDelete: 'RESTRICT' })
author: User;
Defensive patterns

Strategy: validation

Validate before calling

function assertOnDeleteSupported(dataSource: DataSource): string[] {
  const supported = dataSource.driver.supportedOnDeleteTypes
    ? new Set(dataSource.driver.supportedOnDeleteTypes as string[])
    : null;
  if (!supported) return [];
  const problems: string[] = [];
  for (const meta of dataSource.entityMetadatas) {
    for (const rel of meta.relations) {
      if (rel.onDelete && !supported.has(rel.onDelete)) {
        problems.push(`${meta.targetName}.${rel.propertyPath} onDelete='${rel.onDelete}' not supported by ${dataSource.options.type}`);
      }
    }
  }
  return problems;
}

Try / catch

try {
  await dataSource.initialize();
} catch (err) {
  if (err.message.includes('OnDeleteType') && err.message.includes('is not supported for')) {
    // pick a value from driver.supportedOnDeleteTypes
  }
  throw err;
}

Prevention

When it happens

Trigger: Setting @ManyToOne(... { onDelete: 'SET NULL' }) on a driver that does not support that action, or using a non-standard string value (typo) such as 'RESTRICTED' instead of 'RESTRICT'.

Common situations: Switching databases (e.g. SQLite, which supports only a subset of referential actions); typos in onDelete strings; copying MySQL-only options onto a driver that does not implement them.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/c9184386b980e21a. Report an issue: GitHub.