n8n-io/n8n · error · TypeORMError

Entity where values should be inserted is not specified. Cal

Error message

Entity where values should be inserted is not specified. Call "qb.into(entity)" method to specify it.

What it means

QueryBuilder.getMainTableName() throws when expressionMap.mainAlias is null. For an INSERT, the main alias is set by .into(Entity); without it, the builder does not know which table to insert into. The guard fires during createInsertExpression() before any SQL is generated.

Source

Thrown at packages/@n8n/typeorm/src/query-builder/QueryBuilder.ts:594

	 * schema name, otherwise returns escaped table name.
	 */
	protected getTableName(tablePath: string): string {
		return tablePath
			.split('.')
			.map((i) => {
				// this condition need because in SQL Server driver when custom database name was specified and schema name was not, we got `dbName..tableName` string, and doesn't need to escape middle empty string
				if (i === '') return i;
				return this.escape(i);
			})
			.join('.');
	}

	/**
	 * Gets name of the table where insert should be performed.
	 */
	protected getMainTableName(): string {
		if (!this.expressionMap.mainAlias)
			throw new TypeORMError(
				`Entity where values should be inserted is not specified. Call "qb.into(entity)" method to specify it.`,
			);

		if (this.expressionMap.mainAlias.hasMetadata)
			return this.expressionMap.mainAlias.metadata.tablePath;

		return this.expressionMap.mainAlias.tablePath!;
	}

	/**
	 * Specifies FROM which entity's table select/update/delete will be executed.
	 * Also sets a main string alias of the selection data.
	 */
	protected createFromAlias(
		entityTarget: EntityTarget<any> | ((qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>),
		aliasName?: string,
	): Alias {
		// if table has a metadata then find it to properly escape its properties

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Always call .into(Entity) before .values() on an insert builder.
  2. Prefer dataSource.createQueryBuilder().insert().into(Entity).values(payload).
  3. Use repository.insert(payload) which targets the repository's entity implicitly.

Example fix

// before
await dataSource.createQueryBuilder()
  .insert().values({ email }).execute(); // no .into()

// after
await dataSource.createQueryBuilder()
  .insert().into(User).values({ email }).execute();
Defensive patterns

Strategy: validation

Validate before calling

function insertBuilderHasTarget(qb: { expressionMap: { mainAlias?: unknown } }): boolean {
  return qb.expressionMap.mainAlias != null;
}
if (!insertBuilderHasTarget(qb)) throw new Error('call .into(Entity) before .values() on an insert builder');

Type guard

function hasIntoTarget(qb: { expressionMap: { mainAlias?: unknown } }): qb is { expressionMap: { mainAlias: { metadata: unknown } } } {
  return qb.expressionMap.mainAlias != null;
}

Prevention

When it happens

Trigger: Calling .insert().values(payload).execute() (or .getQuery()) without a preceding .into(Entity). Also when .into() is called with an unregistered entity so the alias has no metadata/tablePath.

Common situations: Chaining .insert().values(...) and forgetting .into(). Conditional code that skips .into() in a branch. Passing a non-entity to .into().

Related errors


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