typeorm/typeorm · error · TypeORMError

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

Error message

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

What it means

Thrown by OracleQueryRunner.dropForeignKey when no foreign key matching the supplied name/object is present in the table's cached metadata (table.foreign_keys). The runner first resolves the argument: if it is a TableForeignKey it is used directly, otherwise it searches table.foreignKeys by .name. The optional 'ifExists' flag suppresses the throw when true.

Source

Thrown at src/driver/oracle/OracleQueryRunner.ts:2263

     *
     * @param tableOrName
     * @param foreignKeyOrName
     * @param ifExists
     */
    async dropForeignKey(
        tableOrName: Table | string,
        foreignKeyOrName: TableForeignKey | string,
        ifExists?: boolean,
    ): 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) {
            if (ifExists) return
            throw new TypeORMError(
                `Supplied foreign key was not found in table ${table.name}`,
            )
        }

        foreignKey.name ??= this.dataSource.namingStrategy.foreignKeyName(
            table,
            foreignKey.columnNames,
            this.getTablePath(foreignKey),
            foreignKey.referencedColumnNames,
        )

        const up = this.dropForeignKeySql(table, foreignKey)
        const down = this.createForeignKeySql(table, foreignKey)
        await this.executeQueries(up, down)
        table.removeForeignKey(foreignKey)
    }

    /**

View on GitHub (pinned to 04ff4daedc)

Solutions

  1. Pass ifExists: true (third argument) to make the drop idempotent.
  2. Confirm the FK name against ALL_CONSTRAINTS WHERE CONSTRAINT_TYPE='R' or via table.foreignKeys before calling.
  3. If passing a TableForeignKey object, ensure its .name exactly matches the cached metadata name.
  4. Re-run schema load / use getCachedTable so the metadata reflects current DB state.

Example fix

// before
await queryRunner.dropForeignKey("orders", "fk_orders_user");

// after
await queryRunner.dropForeignKey("orders", "fk_orders_user", true);
Defensive patterns

Strategy: validation

Validate before calling

const table = await queryRunner.getTable("orders");
const fkName = "fk_orders_user";
if ((table?.foreignKeys ?? []).some(fk => fk.name === fkName)) {
  await queryRunner.dropForeignKey("orders", fkName);
}

Type guard

import { TableForeignKey } from "typeorm";
function isTableForeignKey(o: unknown): o is TableForeignKey {
  return typeof o === "object" && o !== null
    && Array.isArray((o as any).columnNames)
    && Array.isArray((o as any).referencedColumnNames);
}

Prevention

When it happens

Trigger: Calling queryRunner.dropForeignKey(table, "fk_name") where 'fk_name' is not among table.foreignKeys[].name. Commonly caused by a mismatched auto-generated FK name (naming strategy), a typo, or dropping an already-removed FK.

Common situations: Naming-strategy changes between migrations; manual DDL applied outside TypeORM that dropped the FK; double-drop in sequenced migrations; schema-qualified vs bare name mismatch.

Related errors


AI-assisted analysis of typeorm/typeorm@04ff4daedc (2026-08-03). Data as JSON: /data/errors/338d31c8fc3edad9.json. Report an issue: GitHub.