typeorm/typeorm · error · TypeORMError
Supplied index ${indexOrName} was not found in table ${table
Error message
Supplied index ${indexOrName} was not found in table ${table.name} What it means
Thrown by SpannerQueryRunner.dropIndex when the supplied index (by TableIndex object or by name string) is not present in the cached table's `indices` array. Suppressed when ifExists:true is passed, which is the idiomatic way to drop indexes that may not exist.
Source
Thrown at src/driver/spanner/SpannerQueryRunner.ts:1680
* @param indexOrName
* @param ifExists
*/
async dropIndex(
tableOrName: Table | string,
indexOrName: TableIndex | string,
ifExists?: boolean,
): Promise<void> {
const table =
tableOrName instanceof Table
? tableOrName
: await this.getCachedTable(tableOrName)
const index =
indexOrName instanceof TableIndex
? indexOrName
: table.indices.find((i) => i.name === indexOrName)
if (!index) {
if (ifExists) return
throw new TypeORMError(
`Supplied index ${indexOrName} was not found in table ${table.name}`,
)
}
// new index may be passed without name. In this case we generate index name manually.
index.name ??= this.generateIndexName(table, index)
const up = this.dropIndexSql(table, index)
const down = this.createIndexSql(table, index)
await this.executeQueries(up, down)
table.removeIndex(index)
}
/**
* Drops an indices from the table.
*
* @param tableOrName
* @param indicesView on GitHub (pinned to 04ff4daedc)
Solutions
- Pass ifExists:true: `await qr.dropIndex('user', 'idx_user_email', true)`.
- Check existence first via getTable and the indices array before dropping.
- Confirm the actual index name from INFORMATION_SCHEMA.INDEXES on spanner (`INDEX_NAME`) and align your migration.
- Use up/down idempotent migration patterns so partial replays don't leave stale drop steps.
Example fix
// before
await queryRunner.dropIndex('user', 'idx_user_email')
// after
await queryRunner.dropIndex('user', 'idx_user_email', true)
// or
const t = await queryRunner.getTable('user')
if (t?.indices.some(i => i.name === 'idx_user_email')) {
await queryRunner.dropIndex(t!, 'idx_user_email')
} Defensive patterns
Strategy: validation
Validate before calling
async function safeDropIndex(qr: QueryRunner, tableName: string, name: string) {
await qr.dropIndex(tableName, name, true) // ifExists
} Type guard
function indexExists(table: Table, name: string): boolean {
return table.indices.some(i => i.name === name)
} Try / catch
try {
await qr.dropIndex('user', 'idx_email')
} catch (e) {
if (e instanceof TypeORMError && /was not found in table/.test(e.message)) return
throw e
} Prevention
- Always pass ifExists:true for dropIndex calls in idempotent migrations.
- Look up the index name from INFORMATION_SCHEMA before dropping.
- Keep index names stable via explicit naming to avoid drift.
When it happens
Trigger: Calling dropIndex(table, 'idx_user_email') where the index was never created, already dropped, or named differently. Common when migrations run partially or when an index name was changed by a naming-strategy update.
Common situations: Re-running a migration after a partial failure; deploying to an environment whose schema drifted; renaming indexes via NamingStrategy changes; concurrency where another process dropped the index first.
Related errors
- Supplied check constraint was not found in table ${table.nam
- Supplied foreign key was not found in table ${table.name}
- Supplied index ${indexOrName} was not found in table ${table
- Supplied index ${indexOrName} was not found in table ${table
- Supplied index ${indexOrName} was not found in table ${table
AI-assisted analysis of typeorm/typeorm@04ff4daedc (2026-08-03).
Data as JSON: /data/errors/9d478e50fc8f09ca.json.
Report an issue: GitHub.