n8n-io/n8n · error · TypeORMError
Entity to work with is not specified!
Error message
Entity to work with is not specified!
What it means
The relationMetadata getter on QueryExpressionMap requires a mainAlias (the entity the builder was created from). It throws TypeORMError when mainAlias is falsy, which happens when createQueryBuilder() was called without a target entity (e.g. raw query builder) but a relation API (.relation(...), .of(...), .set/.add/.remove) was then used.
Source
Thrown at packages/@n8n/typeorm/src/query-builder/QueryExpressionMap.ts:454
if (!alias)
throw new TypeORMError(`"${aliasName}" alias was not found. Maybe you forgot to join it?`);
return alias;
}
findColumnByAliasExpression(aliasExpression: string): ColumnMetadata | undefined {
const [aliasName, propertyPath] = aliasExpression.split('.');
const alias = this.findAliasByName(aliasName);
return alias.metadata.findColumnWithPropertyName(propertyPath);
}
/**
* Gets relation metadata of the relation this query builder works with.
*
* todo: add proper exceptions
*/
get relationMetadata(): RelationMetadata {
if (!this.mainAlias) throw new TypeORMError(`Entity to work with is not specified!`); // todo: better message
const relationMetadata = this.mainAlias.metadata.findRelationWithPropertyPath(
this.relationPropertyPath,
);
if (!relationMetadata)
throw new TypeORMError(
`Relation ${this.relationPropertyPath} was not found in entity ${this.mainAlias.name}`,
); // todo: better message
return relationMetadata;
}
/**
* Copies all properties of the current QueryExpressionMap into a new one.
* Useful when QueryBuilder needs to create a copy of itself.
*/
clone(): QueryExpressionMap {
const map = new QueryExpressionMap(this.connection);View on GitHub (pinned to 5ac6606e81)
Solutions
- Construct the relation builder from an entity-bound builder: dataSource.createQueryBuilder(User).relation('projects').of(user).add(project).
- If you only need raw SQL, drop the .relation() call and use .insert().into(...)/.update() directly.
- Ensure the helper that hands out the builder always seeds it with an entity target.
Example fix
// before
await dataSource.createQueryBuilder().relation('User.projects').of(user).add(p);
// after
await dataSource.createQueryBuilder(User).relation('projects').of(user).add(p); Defensive patterns
Strategy: type-guard
Validate before calling
import { SelectQueryBuilder } from 'typeorm';
function ensureMainAlias<T>(qb: SelectQueryBuilder<T>): asserts qb is SelectQueryBuilder<T> {
if (!qb.expressionMap.mainAlias)
throw new Error('Builder has no main entity alias; create it via createQueryBuilder(Entity).');
} Type guard
function hasMainAlias(qb: SelectQueryBuilder<any>): boolean {
return !!qb.expressionMap.mainAlias;
} Prevention
- Always seed createQueryBuilder with an entity target when relation APIs will be used.
- Wrap relation-builder factories in helpers that take an entity class, not a generic builder.
When it happens
Trigger: Calling dataSource.createQueryBuilder().relation('User.projects') without first binding an entity via .from(User) or createQueryBuilder(User). Using a relation builder off a raw SQL builder returned by createQueryBuilder<SomeShape>().
Common situations: Migrating a raw query to the relation API; helper functions that accept a generic SelectQueryBuilder and accidentally invoke relation operations; chaining .relation() on a builder obtained from manager.createQueryBuilder() with no generic.
Related errors
- Relation ${this.relationPropertyPath} was not found in entit
- Relation with property path ${this.relationPropertyPath} in
- Cannot find alias for relation at ${fullRelationPath}
- Property "${propertyPath}" was not found in "${metadata.targ
- Cannot query across ${relation.relationType} for property ${
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/e7b7673f573e5572.
Report an issue: GitHub.