n8n-io/n8n · error · Error

Column "${column}" was not found in table "${table.name}"

Error message

Column "${column}" was not found in table "${table.name}"

What it means

Inside dropColumns(), each entry is resolved by name against the cached table; if any one is missing it throws (note: a plain `Error`, not TypeORMError). One of the columns in the batch you asked to drop does not exist in the cached table definition.

Source

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

		await this.dropColumns(table, [column]);
	}

	/**
	 * Drops the columns in the table.
	 */
	async dropColumns(tableOrName: Table | string, columns: TableColumn[] | string[]): Promise<void> {
		const table = InstanceChecker.isTable(tableOrName)
			? tableOrName
			: await this.getCachedTable(tableOrName);

		// clone original table and remove column and its constraints from cloned table
		const changedTable = table.clone();
		columns.forEach((column: TableColumn | string) => {
			const columnInstance = InstanceChecker.isTableColumn(column)
				? column
				: table.findColumnByName(column);
			if (!columnInstance)
				throw new Error(`Column "${column}" was not found in table "${table.name}"`);

			changedTable.removeColumn(columnInstance);
			changedTable
				.findColumnUniques(columnInstance)
				.forEach((unique) => changedTable.removeUniqueConstraint(unique));
			changedTable
				.findColumnIndices(columnInstance)
				.forEach((index) => changedTable.removeIndex(index));
			changedTable
				.findColumnForeignKeys(columnInstance)
				.forEach((fk) => changedTable.removeForeignKey(fk));
		});

		await this.recreateTable(changedTable, table);
	}

	/**
	 * Creates a new primary key.

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Filter the list to only columns that currently exist before calling dropColumns.
  2. Verify each column name against the live schema.
  3. Re-fetch the table via getTable() if metadata may be stale.

Example fix

// before
await queryRunner.dropColumns('user', ['a', 'b', 'c']);

// after
const table = await queryRunner.getTable('user');
const toDrop = ['a', 'b', 'c'].filter((n) => table?.findColumnByName(n));
if (toDrop.length) await queryRunner.dropColumns(table!, toDrop as any);
Defensive patterns

Strategy: validation

Validate before calling

const table = await queryRunner.getTable('user');
const toDrop = ['a', 'b', 'c'].filter((n) => table?.findColumnByName(n));
if (toDrop.length) {
  await queryRunner.dropColumns(table!, toDrop as any);
}

Type guard

const filterExistingColumns = async (
  qr: QueryRunner,
  tableName: string,
  names: string[],
): Promise<string[]> => {
  const table = await qr.getTable(tableName);
  return names.filter((n) => table?.findColumnByName(n));
};

Prevention

When it happens

Trigger: Calling dropColumns(table, ['a','b','c']) where one of the names is not a column in the cached table.

Common situations: Re-running a drop migration, a typo in one of several names, a prior migration already removed one column, or stale cached metadata.

Related errors


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