n8n-io/n8n · error · EntityPropertyNotFoundError
Property "${propertyPath}" was not found in "${metadata.targ
Error message
Property "${propertyPath}" was not found in "${metadata.targetName}". Make sure your query is correct. What it means
Inside applyRelationsRecursively, when resolving a nested relation under relationLoadStrategy 'query' or 'join', TypeORM derives the next relationName and relationMetadata. If either is empty (the join/selection couldn't be found in the expression map), it throws EntityPropertyNotFoundError with the original propertyPath and the parent entity targetName. This indicates a relation path whose prefix doesn't correspond to any loaded relation alias.
Source
Thrown at packages/@n8n/typeorm/src/find-options/FindOptionsUtils.ts:329
);
// try to find sub-relations
let relationMetadata: EntityMetadata | undefined;
let relationName: string | undefined;
if (qb.expressionMap.relationLoadStrategy === 'query') {
relationMetadata = relation.inverseEntityMetadata;
relationName = relationAlias;
} else {
const join = qb.expressionMap.joinAttributes.find(
(join) => join.entityOrProperty === selection,
);
relationMetadata = join!.metadata!;
relationName = join!.alias.name;
}
if (!relationName || !relationMetadata) {
throw new EntityPropertyNotFoundError(relation.propertyPath, metadata);
}
this.applyRelationsRecursively(
qb,
allRelations,
relationName,
relationMetadata,
prefix ? prefix + '.' + relation.propertyPath : relation.propertyPath,
);
// join the eager relations of the found relation
// Only supported for "join" relationLoadStrategy
if (qb.expressionMap.relationLoadStrategy === 'join') {
const relMetadata = metadata.relations.find(
(metadata) => metadata.propertyName === relation.propertyPath,
);
if (relMetadata) {
this.joinEagerRelations(qb, relationAlias, relMetadata.inverseEntityMetadata);View on GitHub (pinned to 5ac6606e81)
Solutions
- Verify each segment of a dotted relation path is a relation; for terminal columns use `select`, not `relations`.
- Keep relationLoadStrategy consistent with the query shape (join strategy requires the joins to exist in the expression map).
- When using a custom query builder with find-options, ensure aliases match what setFindOptions expects.
- Build the relations array incrementally to localize the failing segment.
Example fix
// before
await repo.find({ relations: ['profile.address.city'] });
// `city` is a column on Address, not a relation
// after - relations only for related entities, select for columns
@Entity()
class Profile { @OneToOne(() => Address) address!: Address; }
class Address { @Column() city!: string; }
await repo.find({ relations: ['profile', 'profile.address'] }); Defensive patterns
Strategy: validation
Validate before calling
function validateNestedRelations<Entity>(meta: import('@n8n/typeorm').EntityMetadata<Entity>, relations: readonly string[]): void {
for (const path of relations) {
let m = meta;
const segs = path.split('.');
segs.forEach((seg, i) => {
const rel = m.relations.find(x => x.propertyPath === seg);
if (!rel) {
const isLast = i === segs.length - 1;
if (isLast && m.columns.some(c => c.propertyPath === seg)) {
throw new Error(`'${seg}' is a column, not a relation — use select, not relations`);
}
throw new Error(`relation segment '${seg}' not found on ${m.name}`);
}
m = rel.inverseEntityMetadata;
});
}
}
validateNestedRelations(connection.getMetadata(Entity), options.relations ?? []);
await repo.find(options); Type guard
function isTerminalColumn(meta: import('@n8n/typeorm').EntityMetadata<any>, seg: string): boolean {
return meta.columns.some(c => c.propertyPath === seg);
} Prevention
- Ensure every segment of a nested relation path is a relation; use select for terminal columns.
- Keep relationLoadStrategy consistent with the joins present in the query.
- Build nested relations one level at a time to localize failures.
- For custom query builders, ensure aliases match what setFindOptions expects.
When it happens
Trigger: Requesting `relations: ['profile.address.city']` where `profile.address` is loaded but `city` isn't a relation of Address (it's a column); relationLoadStrategy mismatch (query vs join) where the expected join attribute wasn't created; manually-built query builders where the alias expected by recursive resolution was renamed; selecting a relation path before joining it.
Common situations: Deep nested relation paths where a mid-segment is a column not a relation; switching relationLoadStrategy without updating the relations array; custom query builder where aliases don't match what the find-options utility expects; copy-pasting a path from a different entity.
Related errors
- Relation "${notFoundRelations[0]}" was not found; please che
- ${select} column was not found in the ${metadata.name} entit
- ${key} column was not found in the ${metadata.name} entity.
- Property "${propertyPath}" was not found in "${metadata.targ
- Column "${columnName}" was not found in table "${metadata.na
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/f3c9ddc0909c5902.
Report an issue: GitHub.