n8n-io/n8n · error · TypeORMError

Supplied foreign key was not found in table

Error message

Supplied foreign key was not found in table ${table.name}

What it means

dropForeignKey() resolves the foreign key by name (or object) against the cached table; if none matches it throws TypeORMError. The foreign key you are trying to drop does not exist in the table definition TypeORM has loaded.

Solutions

  1. Resolve the actual FK name from the live schema via getTable().foreignKeys before dropping.
  2. Make the drop idempotent — check existence first.
  3. Re-fetch the table via getTable() if metadata may be stale.

Example fix

// before
await queryRunner.dropForeignKey('user', 'FK_user_org');

// after
const table = await queryRunner.getTable('user');
if (table?.foreignKeys.some((fk) => fk.name === 'FK_user_org')) {
  await queryRunner.dropForeignKey(table!, 'FK_user_org');
}
Defensive patterns

Strategy: validation

Validate before calling

const table = await queryRunner.getTable('user');
if (table?.foreignKeys.some((fk) => fk.name === 'FK_user_org')) {
  await queryRunner.dropForeignKey(table!, 'FK_user_org');
}

Type guard

const foreignKeyExists = async (qr: QueryRunner, tableName: string, name: string): Promise<boolean> =>
  Boolean((await qr.getTable(tableName))?.foreignKeys.some((fk) => fk.name === name));

Prevention

When it happens

Trigger: Calling dropForeignKey(table, 'fkName') where 'fkName' is not present in table.foreignKeys of the cached table.

Common situations: Re-running a migration that already dropped it, a typo in the FK name (SQLite often auto-generates these), a prior migration renamed/removed it, or stale cached metadata.

Related errors


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

Appendix: source

Thrown at packages/@n8n/typeorm/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts:960

		await this.recreateTable(changedTable, table);
	}

	/**
	 * Drops a foreign key from the table.
	 */
	async dropForeignKey(
		tableOrName: Table | string,
		foreignKeyOrName: TableForeignKey | string,
	): Promise<void> {
		const table = InstanceChecker.isTable(tableOrName)
			? tableOrName
			: await this.getCachedTable(tableOrName);
		const foreignKey = InstanceChecker.isTableForeignKey(foreignKeyOrName)
			? foreignKeyOrName
			: table.foreignKeys.find((fk) => fk.name === foreignKeyOrName);
		if (!foreignKey)
			throw new TypeORMError(`Supplied foreign key was not found in table ${table.name}`);

		await this.dropForeignKeys(tableOrName, [foreignKey]);
	}

	/**
	 * Drops a foreign keys from the table.
	 */
	async dropForeignKeys(
		tableOrName: Table | string,
		foreignKeys: TableForeignKey[],
	): Promise<void> {
		const table = InstanceChecker.isTable(tableOrName)
			? tableOrName
			: await this.getCachedTable(tableOrName);

		// clone original table and remove foreign keys from cloned table
		const changedTable = table.clone();
		foreignKeys.forEach((foreignKey) => changedTable.removeForeignKey(foreignKey));

View on GitHub (pinned to 5ac6606e81)