{"record":{"id":"40cbc6829a98aee4","repo":"n8n-io/n8n","slug":"cannot-find-alias-for-relation-at-fullrelationpa","errorCode":null,"errorMessage":"Cannot find alias for relation at ${fullRelationPath}","messagePattern":"Cannot find alias for relation at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/QueryBuilder.ts","lineNumber":1145,"sourceCode":"\t\t\tif (alias.metadata.hasEmbeddedWithPropertyPath(part)) {\n\t\t\t\t// If this is an embedded then we should combine the two as part of our lookup.\n\t\t\t\t// Instead of just breaking, we keep going with this in case there's an embedded/relation\n\t\t\t\t// inside an embedded.\n\t\t\t\tpropertyPathParts.unshift(`${propertyPathParts.shift()}.${propertyPathParts.shift()}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (alias.metadata.hasRelationWithPropertyPath(part)) {\n\t\t\t\t// If this is a relation then we should find the aliases\n\t\t\t\t// that match the relation & then continue further down\n\t\t\t\t// the property path\n\t\t\t\tconst joinAttr = this.expressionMap.joinAttributes.find(\n\t\t\t\t\t(joinAttr) => joinAttr.relationPropertyPath === part,\n\t\t\t\t);\n\n\t\t\t\tif (!joinAttr?.alias) {\n\t\t\t\t\tconst fullRelationPath = root.length > 0 ? `${root.join('.')}.${part}` : part;\n\t\t\t\t\tthrow new Error(`Cannot find alias for relation at ${fullRelationPath}`);\n\t\t\t\t}\n\n\t\t\t\talias = joinAttr.alias;\n\t\t\t\troot.push(...part.split('.'));\n\t\t\t\tpropertyPathParts.shift();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (!alias) {\n\t\t\tthrow new Error(`Cannot find alias for property ${propertyPath}`);\n\t\t}\n\n\t\t// Remaining parts are combined back and used to find the actual property path\n\t\tconst aliasPropertyPath = propertyPathParts.join('.');\n","sourceCodeStart":1127,"sourceCodeEnd":1163,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/QueryBuilder.ts#L1127-L1163","documentation":"QueryBuilder relation-path resolver throws when alias.metadata.hasRelationWithPropertyPath(part) is true (the relation exists on the entity) but no matching joinAttribute with an alias is found in expressionMap.joinAttributes. This means the property references a relation that was never joined, so no alias exists for it. The error is thrown from createPropertyPath iteration during where/orderBy/addSelect resolution.","triggerScenarios":"Writing .where('u.members.name = :n') or .orderBy('u.members.name') where 'members' is a @ManyToMany relation on User but no .leftJoin('u.members', 'm') was added. The relation exists in metadata but the join that creates the alias was omitted.","commonSituations":"Querying through a relation without joining it first. Renaming a join alias but not the where path. Assuming eager loading populates a joinable alias (it does not).","solutions":["Add the corresponding leftJoin/innerJoin('alias.relation', 'relAlias') before referencing the relation property in where/orderBy/select.","Ensure the join's relationPropertyPath matches the segment in the property path.","If the relation is loaded eagerly, you still need an explicit join to reference its columns in the same query.","Verify the alias used in the property path matches the join's parent alias."],"exampleFix":"// before\nqb.andWhere('u.members.role = :r', { r: 'admin' }); // members never joined\n\n// after\nqb.leftJoin('u.members', 'm').andWhere('m.role = :r', { r: 'admin' });","handlingStrategy":"validation","validationCode":"function relationIsJoined(qb: { expressionMap: { joinAttributes: Array<{ relationPropertyPath?: string; alias?: unknown }> } }, relationPath: string, part: string): boolean {\n  return qb.expressionMap.joinAttributes.some(ja => ja.relationPropertyPath === part && ja.alias != null);\n}\nif (!relationIsJoined(qb, path, segment)) throw new Error(`relation '${segment}' is not joined; add leftJoin before referencing its columns`);","typeGuard":"function relationAliasExists(qb: { expressionMap: { joinAttributes: Array<{ relationPropertyPath?: string; alias?: unknown }> } }, part: string): boolean {\n  return qb.expressionMap.joinAttributes.some(ja => ja.relationPropertyPath === part && ja.alias != null);\n}","tryCatchPattern":null,"preventionTips":["Add the corresponding leftJoin/innerJoin before referencing a relation's columns in where/orderBy/select.","Match join alias names to the property-path prefix.","Remember eager-loaded relations do not create a joinable alias in the same query.","Lint for where paths that reference relations not present in the joins list."],"tags":["query-builder","join","relation","property-path"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}